github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/resources/resource/resources.go (about) 1 // Copyright 2023 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // Package resource contains Resource related types. 15 package resource 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/gohugoio/hugo/hugofs/glob" 22 "github.com/spf13/cast" 23 ) 24 25 var _ ResourceFinder = (*Resources)(nil) 26 27 // Resources represents a slice of resources, which can be a mix of different types. 28 // I.e. both pages and images etc. 29 type Resources []Resource 30 31 // var _ resource.ResourceFinder = (*Namespace)(nil) 32 // ResourcesConverter converts a given slice of Resource objects to Resources. 33 type ResourcesConverter interface { 34 // For internal use. 35 ToResources() Resources 36 } 37 38 // ByType returns resources of a given resource type (e.g. "image"). 39 func (r Resources) ByType(typ any) Resources { 40 tpstr, err := cast.ToStringE(typ) 41 if err != nil { 42 panic(err) 43 } 44 var filtered Resources 45 46 for _, resource := range r { 47 if resource.ResourceType() == tpstr { 48 filtered = append(filtered, resource) 49 } 50 } 51 return filtered 52 } 53 54 // Get locates the name given in Resources. 55 // The search is case insensitive. 56 func (r Resources) Get(name any) Resource { 57 namestr, err := cast.ToStringE(name) 58 if err != nil { 59 panic(err) 60 } 61 namestr = strings.ToLower(namestr) 62 for _, resource := range r { 63 if strings.EqualFold(namestr, resource.Name()) { 64 return resource 65 } 66 } 67 return nil 68 } 69 70 // GetMatch finds the first Resource matching the given pattern, or nil if none found. 71 // See Match for a more complete explanation about the rules used. 72 func (r Resources) GetMatch(pattern any) Resource { 73 patternstr, err := cast.ToStringE(pattern) 74 if err != nil { 75 panic(err) 76 } 77 78 g, err := glob.GetGlob(patternstr) 79 if err != nil { 80 panic(err) 81 } 82 83 for _, resource := range r { 84 if g.Match(strings.ToLower(resource.Name())) { 85 return resource 86 } 87 } 88 89 return nil 90 } 91 92 // Match gets all resources matching the given base filename prefix, e.g 93 // "*.png" will match all png files. The "*" does not match path delimiters (/), 94 // so if you organize your resources in sub-folders, you need to be explicit about it, e.g.: 95 // "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and 96 // to match all PNG images below the images folder, use "images/**.jpg". 97 // The matching is case insensitive. 98 // Match matches by using the value of Resource.Name, which, by default, is a filename with 99 // path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png". 100 // See https://github.com/gobwas/glob for the full rules set. 101 func (r Resources) Match(pattern any) Resources { 102 patternstr, err := cast.ToStringE(pattern) 103 if err != nil { 104 panic(err) 105 } 106 107 g, err := glob.GetGlob(patternstr) 108 if err != nil { 109 panic(err) 110 } 111 112 var matches Resources 113 for _, resource := range r { 114 if g.Match(strings.ToLower(resource.Name())) { 115 matches = append(matches, resource) 116 } 117 } 118 return matches 119 } 120 121 type translatedResource interface { 122 TranslationKey() string 123 } 124 125 // MergeByLanguage adds missing translations in r1 from r2. 126 func (r Resources) MergeByLanguage(r2 Resources) Resources { 127 result := append(Resources(nil), r...) 128 m := make(map[string]bool) 129 for _, rr := range r { 130 if translated, ok := rr.(translatedResource); ok { 131 m[translated.TranslationKey()] = true 132 } 133 } 134 135 for _, rr := range r2 { 136 if translated, ok := rr.(translatedResource); ok { 137 if _, found := m[translated.TranslationKey()]; !found { 138 result = append(result, rr) 139 } 140 } 141 } 142 return result 143 } 144 145 // MergeByLanguageInterface is the generic version of MergeByLanguage. It 146 // is here just so it can be called from the tpl package. 147 // This is for internal use. 148 func (r Resources) MergeByLanguageInterface(in any) (any, error) { 149 r2, ok := in.(Resources) 150 if !ok { 151 return nil, fmt.Errorf("%T cannot be merged by language", in) 152 } 153 return r.MergeByLanguage(r2), nil 154 } 155 156 // Source is an internal template and not meant for use in the templates. It 157 // may change without notice. 158 type Source interface { 159 Publish() error 160 } 161 162 // ResourceFinder provides methods to find Resources. 163 // Note that GetRemote (as found in resources.GetRemote) is 164 // not covered by this interface, as this is only available as a global template function. 165 type ResourceFinder interface { 166 167 // Get locates the Resource with the given name in the current context (e.g. in .Page.Resources). 168 // 169 // It returns nil if no Resource could found, panics if name is invalid. 170 Get(name any) Resource 171 172 // GetMatch finds the first Resource matching the given pattern, or nil if none found. 173 // 174 // See Match for a more complete explanation about the rules used. 175 // 176 // It returns nil if no Resource could found, panics if pattern is invalid. 177 GetMatch(pattern any) Resource 178 179 // Match gets all resources matching the given base path prefix, e.g 180 // "*.png" will match all png files. The "*" does not match path delimiters (/), 181 // so if you organize your resources in sub-folders, you need to be explicit about it, e.g.: 182 // "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and 183 // to match all PNG images below the images folder, use "images/**.jpg". 184 // 185 // The matching is case insensitive. 186 // 187 // Match matches by using a relative pathwith Unix style slashes (/) and no 188 // leading slash, e.g. "images/logo.png". 189 // 190 // See https://github.com/gobwas/glob for the full rules set. 191 // 192 // See Match for a more complete explanation about the rules used. 193 // 194 // It returns nil if no Resources could found, panics if pattern is invalid. 195 Match(pattern any) Resources 196 197 // ByType returns resources of a given resource type (e.g. "image"). 198 // It returns nil if no Resources could found, panics if typ is invalid. 199 ByType(typ any) Resources 200 }