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  }