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 }