github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/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/gohugoio/hugo/common/maps"
    20  	"github.com/gohugoio/hugo/langs"
    21  	"github.com/gohugoio/hugo/media"
    22  
    23  	"github.com/gohugoio/hugo/common/hugio"
    24  )
    25  
    26  var (
    27  	_ ResourceDataProvider = (*resourceError)(nil)
    28  	_ ResourceError        = (*resourceError)(nil)
    29  )
    30  
    31  // Cloner is for internal use.
    32  type Cloner interface {
    33  	Clone() Resource
    34  }
    35  
    36  // OriginProvider provides the original Resource if this is wrapped.
    37  // This is an internal Hugo interface and not meant for use in the templates.
    38  type OriginProvider interface {
    39  	Origin() Resource
    40  	GetFieldString(pattern string) (string, bool)
    41  }
    42  
    43  // NewResourceError creates a new ResourceError.
    44  func NewResourceError(err error, data any) ResourceError {
    45  	return &resourceError{
    46  		error: err,
    47  		data:  data,
    48  	}
    49  }
    50  
    51  type resourceError struct {
    52  	error
    53  	data any
    54  }
    55  
    56  // The data associated with this error.
    57  func (e *resourceError) Data() any {
    58  	return e.data
    59  }
    60  
    61  // ResourceError is the error return from .Err in Resource in error situations.
    62  type ResourceError interface {
    63  	error
    64  	ResourceDataProvider
    65  }
    66  
    67  // ErrProvider provides an Err.
    68  type ErrProvider interface {
    69  
    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  	ResourceMetaProvider
    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  type ResourceMetaProvider interface {
   112  	// Name is the logical name of this resource. This can be set in the front matter
   113  	// metadata for this resource. If not set, Hugo will assign a value.
   114  	// This will in most cases be the base filename.
   115  	// So, for the image "/some/path/sunset.jpg" this will be "sunset.jpg".
   116  	// The value returned by this method will be used in the GetByPrefix and ByPrefix methods
   117  	// on Resources.
   118  	Name() string
   119  
   120  	// Title returns the title if set in front matter. For content pages, this will be the expected value.
   121  	Title() string
   122  }
   123  
   124  type ResourceParamsProvider interface {
   125  	// Params set in front matter for this resource.
   126  	Params() maps.Params
   127  }
   128  
   129  type ResourceDataProvider interface {
   130  	// Resource specific data set by Hugo.
   131  	// One example would be .Data.Integrity for fingerprinted resources.
   132  	Data() any
   133  }
   134  
   135  // ResourcesLanguageMerger describes an interface for merging resources from a
   136  // different language.
   137  type ResourcesLanguageMerger interface {
   138  	MergeByLanguage(other Resources) Resources
   139  
   140  	// Needed for integration with the tpl package.
   141  	// For internal use.
   142  	MergeByLanguageInterface(other any) (any, error)
   143  }
   144  
   145  // Identifier identifies a resource.
   146  type Identifier interface {
   147  	Key() string
   148  }
   149  
   150  // ContentResource represents a Resource that provides a way to get to its content.
   151  // Most Resource types in Hugo implements this interface, including Page.
   152  type ContentResource interface {
   153  	MediaType() media.Type
   154  	ContentProvider
   155  }
   156  
   157  // ContentProvider provides Content.
   158  // This should be used with care, as it will read the file content into memory, but it
   159  // should be cached as effectively as possible by the implementation.
   160  type ContentProvider interface {
   161  	// Content returns this resource's content. It will be equivalent to reading the content
   162  	// that RelPermalink points to in the published folder.
   163  	// The return type will be contextual, and should be what you would expect:
   164  	// * Page: template.HTML
   165  	// * JSON: String
   166  	// * Etc.
   167  	Content(context.Context) (any, error)
   168  }
   169  
   170  // OpenReadSeekCloser allows setting some other way (than reading from a filesystem)
   171  // to open or create a ReadSeekCloser.
   172  type OpenReadSeekCloser func() (hugio.ReadSeekCloser, error)
   173  
   174  // ReadSeekCloserResource is a Resource that supports loading its content.
   175  type ReadSeekCloserResource interface {
   176  	MediaType() media.Type
   177  	hugio.ReadSeekCloserProvider
   178  }
   179  
   180  // LengthProvider is a Resource that provides a length
   181  // (typically the length of the content).
   182  type LengthProvider interface {
   183  	Len(context.Context) int
   184  }
   185  
   186  // LanguageProvider is a Resource in a language.
   187  type LanguageProvider interface {
   188  	Language() *langs.Language
   189  }
   190  
   191  // TranslationKeyProvider connects translations of the same Resource.
   192  type TranslationKeyProvider interface {
   193  	TranslationKey() string
   194  }
   195  
   196  // UnmarshableResource represents a Resource that can be unmarshaled to some other format.
   197  type UnmarshableResource interface {
   198  	ReadSeekCloserResource
   199  	Identifier
   200  }
   201  
   202  type resourceTypesHolder struct {
   203  	mediaType    media.Type
   204  	resourceType string
   205  }
   206  
   207  func (r resourceTypesHolder) MediaType() media.Type {
   208  	return r.mediaType
   209  }
   210  
   211  func (r resourceTypesHolder) ResourceType() string {
   212  	return r.resourceType
   213  }
   214  
   215  func NewResourceTypesProvider(mediaType media.Type, resourceType string) ResourceTypesProvider {
   216  	return resourceTypesHolder{mediaType: mediaType, resourceType: resourceType}
   217  }
   218  
   219  type languageHolder struct {
   220  	lang *langs.Language
   221  }
   222  
   223  func (l languageHolder) Language() *langs.Language {
   224  	return l.lang
   225  }
   226  
   227  func NewLanguageProvider(lang *langs.Language) LanguageProvider {
   228  	return languageHolder{lang: lang}
   229  }