github.com/neohugo/neohugo@v0.123.8/resources/resource/resourcetypes.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  	"context"
    18  
    19  	"github.com/neohugo/neohugo/common/maps"
    20  	"github.com/neohugo/neohugo/common/types"
    21  	"github.com/neohugo/neohugo/langs"
    22  	"github.com/neohugo/neohugo/media"
    23  
    24  	"github.com/neohugo/neohugo/common/hugio"
    25  )
    26  
    27  var (
    28  	_ ResourceDataProvider = (*resourceError)(nil)
    29  	_ ResourceError        = (*resourceError)(nil)
    30  )
    31  
    32  // Cloner is for internal use.
    33  type Cloner interface {
    34  	Clone() Resource
    35  }
    36  
    37  // OriginProvider provides the original Resource if this is wrapped.
    38  // This is an internal Hugo interface and not meant for use in the templates.
    39  type OriginProvider interface {
    40  	Origin() Resource
    41  	GetFieldString(pattern string) (string, bool)
    42  }
    43  
    44  // NewResourceError creates a new ResourceError.
    45  func NewResourceError(err error, data any) ResourceError {
    46  	return &resourceError{
    47  		error: err,
    48  		data:  data,
    49  	}
    50  }
    51  
    52  type resourceError struct {
    53  	error
    54  	data any
    55  }
    56  
    57  // The data associated with this error.
    58  func (e *resourceError) Data() any {
    59  	return e.data
    60  }
    61  
    62  // ResourceError is the error return from .Err in Resource in error situations.
    63  type ResourceError interface {
    64  	error
    65  	ResourceDataProvider
    66  }
    67  
    68  // ErrProvider provides an Err.
    69  type ErrProvider interface {
    70  	// Err returns an error if this resource is in an error state.
    71  	// This will currently only be set for resources obtained from resources.GetRemote.
    72  	Err() ResourceError
    73  }
    74  
    75  // Resource represents a linkable resource, i.e. a content page, image etc.
    76  type Resource interface {
    77  	ResourceTypeProvider
    78  	MediaTypeProvider
    79  	ResourceLinksProvider
    80  	ResourceNameTitleProvider
    81  	ResourceParamsProvider
    82  	ResourceDataProvider
    83  	ErrProvider
    84  }
    85  
    86  type ResourceTypeProvider interface {
    87  	// ResourceType is the resource type. For most file types, this is the main
    88  	// part of the MIME type, e.g. "image", "application", "text" etc.
    89  	// For content pages, this value is "page".
    90  	ResourceType() string
    91  }
    92  
    93  type ResourceTypesProvider interface {
    94  	ResourceTypeProvider
    95  	MediaTypeProvider
    96  }
    97  
    98  type MediaTypeProvider interface {
    99  	// MediaType is this resource's MIME type.
   100  	MediaType() media.Type
   101  }
   102  
   103  type ResourceLinksProvider interface {
   104  	// Permalink represents the absolute link to this resource.
   105  	Permalink() string
   106  
   107  	// RelPermalink represents the host relative link to this resource.
   108  	RelPermalink() string
   109  }
   110  
   111  // ResourceMetaProvider provides metadata about a resource.
   112  type ResourceMetaProvider interface {
   113  	ResourceNameTitleProvider
   114  	ResourceParamsProvider
   115  }
   116  
   117  type WithResourceMetaProvider interface {
   118  	// WithResourceMeta creates a new Resource with the given metadata.
   119  	// For internal use.
   120  	WithResourceMeta(ResourceMetaProvider) Resource
   121  }
   122  
   123  type ResourceNameTitleProvider interface {
   124  	// Name is the logical name of this resource. This can be set in the front matter
   125  	// metadata for this resource. If not set, Hugo will assign a value.
   126  	// This will in most cases be the base filename.
   127  	// So, for the image "/some/path/sunset.jpg" this will be "sunset.jpg".
   128  	// The value returned by this method will be used in the GetByPrefix and ByPrefix methods
   129  	// on Resources.
   130  	Name() string
   131  
   132  	// Title returns the title if set in front matter. For content pages, this will be the expected value.
   133  	Title() string
   134  }
   135  
   136  type NameNormalizedProvider interface {
   137  	// NameNormalized is the normalized name of this resource.
   138  	// For internal use (for now).
   139  	NameNormalized() string
   140  }
   141  
   142  type ResourceParamsProvider interface {
   143  	// Params set in front matter for this resource.
   144  	Params() maps.Params
   145  }
   146  
   147  type ResourceDataProvider interface {
   148  	// Resource specific data set by Hugo.
   149  	// One example would be .Data.Integrity for fingerprinted resources.
   150  	Data() any
   151  }
   152  
   153  // ResourcesLanguageMerger describes an interface for merging resources from a
   154  // different language.
   155  type ResourcesLanguageMerger interface {
   156  	MergeByLanguage(other Resources) Resources
   157  
   158  	// Needed for integration with the tpl package.
   159  	// For internal use.
   160  	MergeByLanguageInterface(other any) (any, error)
   161  }
   162  
   163  // Identifier identifies a resource.
   164  type Identifier interface {
   165  	// Key is is mostly for internal use and should be considered opaque.
   166  	// This value may change between Hugo versions.
   167  	Key() string
   168  }
   169  
   170  // WeightProvider provides a weight.
   171  type WeightProvider interface {
   172  	Weight() int
   173  }
   174  
   175  // Weight0Provider provides a weight that's considered before the WeightProvider in sorting.
   176  // This allows the weight set on a given term to win.
   177  type Weight0Provider interface {
   178  	Weight0() int
   179  }
   180  
   181  // ContentResource represents a Resource that provides a way to get to its content.
   182  // Most Resource types in Hugo implements this interface, including Page.
   183  type ContentResource interface {
   184  	MediaType() media.Type
   185  	ContentProvider
   186  }
   187  
   188  // ContentProvider provides Content.
   189  // This should be used with care, as it will read the file content into memory, but it
   190  // should be cached as effectively as possible by the implementation.
   191  type ContentProvider interface {
   192  	// Content returns this resource's content. It will be equivalent to reading the content
   193  	// that RelPermalink points to in the published folder.
   194  	// The return type will be contextual, and should be what you would expect:
   195  	// * Page: template.HTML
   196  	// * JSON: String
   197  	// * Etc.
   198  	Content(context.Context) (any, error)
   199  }
   200  
   201  // ReadSeekCloserResource is a Resource that supports loading its content.
   202  type ReadSeekCloserResource interface {
   203  	MediaType() media.Type
   204  	hugio.ReadSeekCloserProvider
   205  }
   206  
   207  // LengthProvider is a Resource that provides a length
   208  // (typically the length of the content).
   209  type LengthProvider interface {
   210  	Len(context.Context) int
   211  }
   212  
   213  // LanguageProvider is a Resource in a language.
   214  type LanguageProvider interface {
   215  	Language() *langs.Language
   216  }
   217  
   218  // TranslationKeyProvider connects translations of the same Resource.
   219  type TranslationKeyProvider interface {
   220  	TranslationKey() string
   221  }
   222  
   223  // Staler controls stale state of a Resource. A stale resource should be discarded.
   224  type Staler interface {
   225  	StaleMarker
   226  	StaleInfo
   227  }
   228  
   229  // StaleMarker marks a Resource as stale.
   230  type StaleMarker interface {
   231  	MarkStale()
   232  }
   233  
   234  // StaleInfo tells if a resource is marked as stale.
   235  type StaleInfo interface {
   236  	IsStale() bool
   237  }
   238  
   239  // IsStaleAny reports whether any of the os is marked as stale.
   240  func IsStaleAny(os ...any) bool {
   241  	for _, o := range os {
   242  		if s, ok := o.(StaleInfo); ok && s.IsStale() {
   243  			return true
   244  		}
   245  	}
   246  	return false
   247  }
   248  
   249  // MarkStale will mark any of the oses as stale, if possible.
   250  func MarkStale(os ...any) {
   251  	for _, o := range os {
   252  		if types.IsNil(o) {
   253  			continue
   254  		}
   255  		if s, ok := o.(StaleMarker); ok {
   256  			s.MarkStale()
   257  		}
   258  	}
   259  }
   260  
   261  // UnmarshableResource represents a Resource that can be unmarshaled to some other format.
   262  type UnmarshableResource interface {
   263  	ReadSeekCloserResource
   264  	Identifier
   265  }
   266  
   267  type resourceTypesHolder struct {
   268  	mediaType    media.Type
   269  	resourceType string
   270  }
   271  
   272  func (r resourceTypesHolder) MediaType() media.Type {
   273  	return r.mediaType
   274  }
   275  
   276  func (r resourceTypesHolder) ResourceType() string {
   277  	return r.resourceType
   278  }
   279  
   280  func NewResourceTypesProvider(mediaType media.Type, resourceType string) ResourceTypesProvider {
   281  	return resourceTypesHolder{mediaType: mediaType, resourceType: resourceType}
   282  }