github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/resources/resource/resources.go (about) 1 // Copyright 2019 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 15 16 import ( 17 "fmt" 18 "strings" 19 20 "github.com/gohugoio/hugo/hugofs/glob" 21 ) 22 23 // Resources represents a slice of resources, which can be a mix of different types. 24 // I.e. both pages and images etc. 25 type Resources []Resource 26 27 // ResourcesConverter converts a given slice of Resource objects to Resources. 28 type ResourcesConverter interface { 29 ToResources() Resources 30 } 31 32 // ByType returns resources of a given resource type (ie. "image"). 33 func (r Resources) ByType(tp string) Resources { 34 var filtered Resources 35 36 for _, resource := range r { 37 if resource.ResourceType() == tp { 38 filtered = append(filtered, resource) 39 } 40 } 41 return filtered 42 } 43 44 // GetMatch finds the first Resource matching the given pattern, or nil if none found. 45 // See Match for a more complete explanation about the rules used. 46 func (r Resources) GetMatch(pattern string) Resource { 47 g, err := glob.GetGlob(pattern) 48 if err != nil { 49 return nil 50 } 51 52 for _, resource := range r { 53 if g.Match(strings.ToLower(resource.Name())) { 54 return resource 55 } 56 } 57 58 return nil 59 } 60 61 // Match gets all resources matching the given base filename prefix, e.g 62 // "*.png" will match all png files. The "*" does not match path delimiters (/), 63 // so if you organize your resources in sub-folders, you need to be explicit about it, e.g.: 64 // "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and 65 // to match all PNG images below the images folder, use "images/**.jpg". 66 // The matching is case insensitive. 67 // Match matches by using the value of Resource.Name, which, by default, is a filename with 68 // path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png". 69 // See https://github.com/gobwas/glob for the full rules set. 70 func (r Resources) Match(pattern string) Resources { 71 g, err := glob.GetGlob(pattern) 72 if err != nil { 73 return nil 74 } 75 76 var matches Resources 77 for _, resource := range r { 78 if g.Match(strings.ToLower(resource.Name())) { 79 matches = append(matches, resource) 80 } 81 } 82 return matches 83 } 84 85 type translatedResource interface { 86 TranslationKey() string 87 } 88 89 // MergeByLanguage adds missing translations in r1 from r2. 90 func (r Resources) MergeByLanguage(r2 Resources) Resources { 91 result := append(Resources(nil), r...) 92 m := make(map[string]bool) 93 for _, rr := range r { 94 if translated, ok := rr.(translatedResource); ok { 95 m[translated.TranslationKey()] = true 96 } 97 } 98 99 for _, rr := range r2 { 100 if translated, ok := rr.(translatedResource); ok { 101 if _, found := m[translated.TranslationKey()]; !found { 102 result = append(result, rr) 103 } 104 } 105 } 106 return result 107 } 108 109 // MergeByLanguageInterface is the generic version of MergeByLanguage. It 110 // is here just so it can be called from the tpl package. 111 func (r Resources) MergeByLanguageInterface(in interface{}) (interface{}, error) { 112 r2, ok := in.(Resources) 113 if !ok { 114 return nil, fmt.Errorf("%T cannot be merged by language", in) 115 } 116 return r.MergeByLanguage(r2), nil 117 } 118 119 // Source is an internal template and not meant for use in the templates. It 120 // may change without notice. 121 type Source interface { 122 Publish() error 123 }