1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

Direct avatar rendering (#13649)

* Direct avatar rendering

This adds new template helpers for avatar rendering which output image
elements with direct links to avatars which makes them cacheable by the
browsers.

This should be a major performance improvment for pages with many avatars.

* fix avatars of other user's profile pages

* fix top border on user avatar name

* uncircle avatars

* remove old incomplete avatar selector

* use title attribute for name and add it back on blame

* minor refactor

* tweak comments

* fix url path join and adjust test to new result

* dedupe functions
This commit is contained in:
silverwind
2020-12-03 19:46:11 +01:00
committed by GitHub
parent 0d35ef5b43
commit 9269a038a4
62 changed files with 435 additions and 340 deletions

View File

@@ -88,7 +88,6 @@ func NewFuncMap() []template.FuncMap {
"AllowedReactions": func() []string {
return setting.UI.Reactions
},
"AvatarLink": models.AvatarLink,
"Safe": Safe,
"SafeJS": SafeJS,
"Str2html": Str2html,
@@ -339,7 +338,9 @@ func NewFuncMap() []template.FuncMap {
}
return false
},
"svg": SVG,
"svg": SVG,
"avatar": Avatar,
"avatarByEmail": AvatarByEmail,
"SortArrow": func(normSort, revSort, urlSort string, isDefault bool) template.HTML {
// if needed
if len(normSort) == 0 || len(urlSort) == 0 {
@@ -499,18 +500,38 @@ func NewTextFuncMap() []texttmpl.FuncMap {
var widthRe = regexp.MustCompile(`width="[0-9]+?"`)
var heightRe = regexp.MustCompile(`height="[0-9]+?"`)
// SVG render icons - arguments icon name (string), size (int), class (string)
func SVG(icon string, others ...interface{}) template.HTML {
size := 16
func parseOthers(defaultSize int, defaultClass string, others ...interface{}) (int, string) {
size := defaultSize
if len(others) > 0 && others[0].(int) != 0 {
size = others[0].(int)
}
class := ""
class := defaultClass
if len(others) > 1 && others[1].(string) != "" {
class = others[1].(string)
if defaultClass == "" {
class = others[1].(string)
} else {
class = defaultClass + " " + others[1].(string)
}
}
return size, class
}
func avatarHTML(src string, size int, class string, name string) template.HTML {
sizeStr := fmt.Sprintf(`%d`, size)
if name == "" {
name = "avatar"
}
return template.HTML(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
}
// SVG render icons - arguments icon name (string), size (int), class (string)
func SVG(icon string, others ...interface{}) template.HTML {
size, class := parseOthers(16, "", others...)
if svgStr, ok := svg.SVGs[icon]; ok {
if size != 16 {
svgStr = widthRe.ReplaceAllString(svgStr, fmt.Sprintf(`width="%d"`, size))
@@ -524,6 +545,38 @@ func SVG(icon string, others ...interface{}) template.HTML {
return template.HTML("")
}
// Avatar renders user and repo avatars. args: user/repo, size (int), class (string)
func Avatar(item interface{}, others ...interface{}) template.HTML {
size, class := parseOthers(28, "ui avatar image", others...)
if user, ok := item.(*models.User); ok {
src := user.RealSizedAvatarLink(size * 2) // request double size for finer rendering
if src != "" {
return avatarHTML(src, size, class, user.DisplayName())
}
}
if repo, ok := item.(*models.Repository); ok {
src := repo.RelAvatarLink()
if src != "" {
return avatarHTML(src, size, class, repo.FullName())
}
}
return template.HTML("")
}
// AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string)
func AvatarByEmail(email string, name string, others ...interface{}) template.HTML {
size, class := parseOthers(28, "ui avatar image", others...)
src := models.SizedAvatarLink(email, size*2) // request double size for finer rendering
if src != "" {
return avatarHTML(src, size, class, name)
}
return template.HTML("")
}
// Safe render raw as HTML
func Safe(raw string) template.HTML {
return template.HTML(raw)