// Copyright 2025 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package fileicon import ( "html/template" "path" "strings" "sync" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/options" "code.gitea.io/gitea/modules/reqctx" "code.gitea.io/gitea/modules/svg" ) type materialIconRulesData struct { FileNames map[string]string `json:"fileNames"` FolderNames map[string]string `json:"folderNames"` FileExtensions map[string]string `json:"fileExtensions"` } type MaterialIconProvider struct { once sync.Once rules *materialIconRulesData svgs map[string]string } var materialIconProvider MaterialIconProvider func DefaultMaterialIconProvider() *MaterialIconProvider { materialIconProvider.once.Do(materialIconProvider.loadData) return &materialIconProvider } func (m *MaterialIconProvider) loadData() { buf, err := options.AssetFS().ReadFile("fileicon/material-icon-rules.json") if err != nil { log.Error("Failed to read material icon rules: %v", err) return } err = json.Unmarshal(buf, &m.rules) if err != nil { log.Error("Failed to unmarshal material icon rules: %v", err) return } buf, err = options.AssetFS().ReadFile("fileicon/material-icon-svgs.json") if err != nil { log.Error("Failed to read material icon rules: %v", err) return } err = json.Unmarshal(buf, &m.svgs) if err != nil { log.Error("Failed to unmarshal material icon rules: %v", err) return } log.Debug("Loaded material icon rules and SVG images") } func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name, svg string) template.HTML { data := ctx.GetData() renderedSVGs, _ := data["_RenderedSVGs"].(map[string]bool) if renderedSVGs == nil { renderedSVGs = make(map[string]bool) data["_RenderedSVGs"] = renderedSVGs } // This part is a bit hacky, but it works really well. It should be safe to do so because all SVG icons are generated by us. // Will try to refactor this in the future. if !strings.HasPrefix(svg, "