diff --git a/modules/html/html.go b/modules/html/html.go new file mode 100644 index 0000000000..dafdb503b6 --- /dev/null +++ b/modules/html/html.go @@ -0,0 +1,34 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package html + +// ParseSizeAndClass get size and class from string with default values +// If present, "others" expects the new size first and then the classes to use +func ParseSizeAndClass(defaultSize int, defaultClass string, others ...interface{}) (int, string) { + if len(others) == 0 { + return defaultSize, defaultClass + } + + size := defaultSize + _size, ok := others[0].(int) + if ok && _size != 0 { + size = _size + } + + if len(others) == 1 { + return size, defaultClass + } + + class := defaultClass + if _class, ok := others[1].(string); ok && _class != "" { + if defaultClass == "" { + class = _class + } else { + class = defaultClass + " " + _class + } + } + + return size, class +} diff --git a/modules/svg/svg.go b/modules/svg/svg.go index 1d1f8a90eb..4e13d92d41 100644 --- a/modules/svg/svg.go +++ b/modules/svg/svg.go @@ -4,10 +4,43 @@ package svg -// SVGs contains discovered SVGs -var SVGs map[string]string +import ( + "fmt" + "html/template" + "regexp" + "strings" + + "code.gitea.io/gitea/modules/html" +) + +var ( + // SVGs contains discovered SVGs + SVGs map[string]string + + widthRe = regexp.MustCompile(`width="[0-9]+?"`) + heightRe = regexp.MustCompile(`height="[0-9]+?"`) +) + +const defaultSize = 16 // Init discovers SVGs and populates the `SVGs` variable func Init() { SVGs = Discover() } + +// Render render icons - arguments icon name (string), size (int), class (string) +func RenderHTML(icon string, others ...interface{}) template.HTML { + size, class := html.ParseSizeAndClass(defaultSize, "", others...) + + if svgStr, ok := SVGs[icon]; ok { + if size != defaultSize { + svgStr = widthRe.ReplaceAllString(svgStr, fmt.Sprintf(`width="%d"`, size)) + svgStr = heightRe.ReplaceAllString(svgStr, fmt.Sprintf(`height="%d"`, size)) + } + if class != "" { + svgStr = strings.Replace(svgStr, `class="`, fmt.Sprintf(`class="%s `, class), 1) + } + return template.HTML(svgStr) + } + return template.HTML("") +} diff --git a/modules/templates/helper.go b/modules/templates/helper.go index a127b98dc2..c5434b7c63 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -35,6 +35,7 @@ import ( "code.gitea.io/gitea/modules/emoji" "code.gitea.io/gitea/modules/git" giturl "code.gitea.io/gitea/modules/git/url" + gitea_html "code.gitea.io/gitea/modules/html" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" @@ -348,7 +349,7 @@ func NewFuncMap() []template.FuncMap { } return false }, - "svg": SVG, + "svg": svg.RenderHTML, "avatar": Avatar, "avatarHTML": AvatarHTML, "avatarByAction": AvatarByAction, @@ -363,17 +364,17 @@ func NewFuncMap() []template.FuncMap { if len(urlSort) == 0 && isDefault { // if sort is sorted as default add arrow tho this table header if isDefault { - return SVG("octicon-triangle-down", 16) + return svg.RenderHTML("octicon-triangle-down", 16) } } else { // if sort arg is in url test if it correlates with column header sort arguments // the direction of the arrow should indicate the "current sort order", up means ASC(normal), down means DESC(rev) if urlSort == normSort { // the table is sorted with this header normal - return SVG("octicon-triangle-up", 16) + return svg.RenderHTML("octicon-triangle-up", 16) } else if urlSort == revSort { // the table is sorted with this header reverse - return SVG("octicon-triangle-down", 16) + return svg.RenderHTML("octicon-triangle-down", 16) } } // the table is NOT sorted with this header @@ -594,29 +595,6 @@ func NewTextFuncMap() []texttmpl.FuncMap { }} } -var ( - widthRe = regexp.MustCompile(`width="[0-9]+?"`) - heightRe = regexp.MustCompile(`height="[0-9]+?"`) -) - -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 := defaultClass - if len(others) > 1 && others[1].(string) != "" { - if defaultClass == "" { - class = others[1].(string) - } else { - class = defaultClass + " " + others[1].(string) - } - } - - return size, class -} - // AvatarHTML creates the HTML for an avatar func AvatarHTML(src string, size int, class, name string) template.HTML { sizeStr := fmt.Sprintf(`%d`, size) @@ -628,26 +606,9 @@ func AvatarHTML(src string, size int, class, name string) template.HTML { return template.HTML(``) } -// 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)) - svgStr = heightRe.ReplaceAllString(svgStr, fmt.Sprintf(`height="%d"`, size)) - } - if class != "" { - svgStr = strings.Replace(svgStr, `class="`, fmt.Sprintf(`class="%s `, class), 1) - } - return template.HTML(svgStr) - } - return template.HTML("") -} - // Avatar renders user avatars. args: user, size (int), class (string) func Avatar(item interface{}, others ...interface{}) template.HTML { - size, class := parseOthers(avatars.DefaultAvatarPixelSize, "ui avatar vm", others...) + size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, "ui avatar vm", others...) switch t := item.(type) { case *user_model.User: @@ -678,7 +639,7 @@ func AvatarByAction(action *activities_model.Action, others ...interface{}) temp // RepoAvatar renders repo avatars. args: repo, size(int), class (string) func RepoAvatar(repo *repo_model.Repository, others ...interface{}) template.HTML { - size, class := parseOthers(avatars.DefaultAvatarPixelSize, "ui avatar", others...) + size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, "ui avatar", others...) src := repo.RelAvatarLink() if src != "" { @@ -689,7 +650,7 @@ func RepoAvatar(repo *repo_model.Repository, others ...interface{}) template.HTM // AvatarByEmail renders avatars by email address. args: email, name, size (int), class (string) func AvatarByEmail(email, name string, others ...interface{}) template.HTML { - size, class := parseOthers(avatars.DefaultAvatarPixelSize, "ui avatar", others...) + size, class := gitea_html.ParseSizeAndClass(avatars.DefaultAvatarPixelSize, "ui avatar", others...) src := avatars.GenerateEmailAvatarFastLink(email, size*setting.Avatar.RenderedSizeFactor) if src != "" {