code.gitea.io/gitea@v1.22.3/modules/svg/svg.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package svg 5 6 import ( 7 "fmt" 8 "html/template" 9 "path" 10 "strings" 11 12 gitea_html "code.gitea.io/gitea/modules/html" 13 "code.gitea.io/gitea/modules/log" 14 "code.gitea.io/gitea/modules/public" 15 ) 16 17 var svgIcons map[string]string 18 19 const defaultSize = 16 20 21 // Init discovers SVG icons and populates the `svgIcons` variable 22 func Init() error { 23 const svgAssetsPath = "assets/img/svg" 24 files, err := public.AssetFS().ListFiles(svgAssetsPath) 25 if err != nil { 26 return err 27 } 28 29 svgIcons = make(map[string]string, len(files)) 30 for _, file := range files { 31 if path.Ext(file) != ".svg" { 32 continue 33 } 34 bs, err := public.AssetFS().ReadFile(svgAssetsPath, file) 35 if err != nil { 36 log.Error("Failed to read SVG file %s: %v", file, err) 37 } else { 38 svgIcons[file[:len(file)-4]] = string(Normalize(bs, defaultSize)) 39 } 40 } 41 return nil 42 } 43 44 func MockIcon(icon string) func() { 45 if svgIcons == nil { 46 svgIcons = make(map[string]string) 47 } 48 orig, exist := svgIcons[icon] 49 svgIcons[icon] = fmt.Sprintf(`<svg class="svg %s" width="%d" height="%d"></svg>`, icon, defaultSize, defaultSize) 50 return func() { 51 if exist { 52 svgIcons[icon] = orig 53 } else { 54 delete(svgIcons, icon) 55 } 56 } 57 } 58 59 // RenderHTML renders icons - arguments icon name (string), size (int), class (string) 60 func RenderHTML(icon string, others ...any) template.HTML { 61 size, class := gitea_html.ParseSizeAndClass(defaultSize, "", others...) 62 if svgStr, ok := svgIcons[icon]; ok { 63 // the code is somewhat hacky, but it just works, because the SVG contents are all normalized 64 if size != defaultSize { 65 svgStr = strings.Replace(svgStr, fmt.Sprintf(`width="%d"`, defaultSize), fmt.Sprintf(`width="%d"`, size), 1) 66 svgStr = strings.Replace(svgStr, fmt.Sprintf(`height="%d"`, defaultSize), fmt.Sprintf(`height="%d"`, size), 1) 67 } 68 if class != "" { 69 svgStr = strings.Replace(svgStr, `class="`, fmt.Sprintf(`class="%s `, class), 1) 70 } 71 return template.HTML(svgStr) 72 } 73 // during test (or something wrong happens), there is no SVG loaded, so use a dummy span to tell that the icon is missing 74 return template.HTML(fmt.Sprintf("<span>%s(%d/%s)</span>", template.HTMLEscapeString(icon), size, template.HTMLEscapeString(class))) 75 }