summaryrefslogtreecommitdiffstats
path: root/resources/resource
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-01-02 11:58:32 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-01-02 14:25:37 +0100
commitce8a09a4c0661dece931ab1173e4f09e8e04aa38 (patch)
tree870372211e342312d0ab3034ee03285c6f698f9d /resources/resource
parent669ada436787311cc5d02dae5b88e60a09adda58 (diff)
resources: Move resource interfaces into its own package
Diffstat (limited to 'resources/resource')
-rw-r--r--resources/resource/resources.go123
-rw-r--r--resources/resource/resourcetypes.go106
2 files changed, 229 insertions, 0 deletions
diff --git a/resources/resource/resources.go b/resources/resource/resources.go
new file mode 100644
index 000000000..5c661c24e
--- /dev/null
+++ b/resources/resource/resources.go
@@ -0,0 +1,123 @@
+// Copyright 2019 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package resource
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/gohugoio/hugo/resources/internal"
+)
+
+// Resources represents a slice of resources, which can be a mix of different types.
+// I.e. both pages and images etc.
+type Resources []Resource
+
+// ResourcesConverter converts a given slice of Resource objects to Resources.
+type ResourcesConverter interface {
+ ToResources() Resources
+}
+
+// ByType returns resources of a given resource type (ie. "image").
+func (r Resources) ByType(tp string) Resources {
+ var filtered Resources
+
+ for _, resource := range r {
+ if resource.ResourceType() == tp {
+ filtered = append(filtered, resource)
+ }
+ }
+ return filtered
+}
+
+// GetMatch finds the first Resource matching the given pattern, or nil if none found.
+// See Match for a more complete explanation about the rules used.
+func (r Resources) GetMatch(pattern string) Resource {
+ g, err := internal.GetGlob(pattern)
+ if err != nil {
+ return nil
+ }
+
+ for _, resource := range r {
+ if g.Match(strings.ToLower(resource.Name())) {
+ return resource
+ }
+ }
+
+ return nil
+}
+
+// Match gets all resources matching the given base filename prefix, e.g
+// "*.png" will match all png files. The "*" does not match path delimiters (/),
+// so if you organize your resources in sub-folders, you need to be explicit about it, e.g.:
+// "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and
+// to match all PNG images below the images folder, use "images/**.jpg".
+// The matching is case insensitive.
+// Match matches by using the value of Resource.Name, which, by default, is a filename with
+// path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png".
+// See https://github.com/gobwas/glob for the full rules set.
+func (r Resources) Match(pattern string) Resources {
+ g, err := internal.GetGlob(pattern)
+ if err != nil {
+ return nil
+ }
+
+ var matches Resources
+ for _, resource := range r {
+ if g.Match(strings.ToLower(resource.Name())) {
+ matches = append(matches, resource)
+ }
+ }
+ return matches
+}
+
+type translatedResource interface {
+ TranslationKey() string
+}
+
+// MergeByLanguage adds missing translations in r1 from r2.
+func (r Resources) MergeByLanguage(r2 Resources) Resources {
+ result := append(Resources(nil), r...)
+ m := make(map[string]bool)
+ for _, rr := range r {
+ if translated, ok := rr.(translatedResource); ok {
+ m[translated.TranslationKey()] = true
+ }
+ }
+
+ for _, rr := range r2 {
+ if translated, ok := rr.(translatedResource); ok {
+ if _, found := m[translated.TranslationKey()]; !found {
+ result = append(result, rr)
+ }
+ }
+ }
+ return result
+}
+
+// MergeByLanguageInterface is the generic version of MergeByLanguage. It
+// is here just so it can be called from the tpl package.
+func (r Resources) MergeByLanguageInterface(in interface{}) (interface{}, error) {
+ r2, ok := in.(Resources)
+ if !ok {
+ return nil, fmt.Errorf("%T cannot be merged by language", in)
+ }
+ return r.MergeByLanguage(r2), nil
+}
+
+// Source is an internal template and not meant for use in the templates. It
+// may change without notice.
+type Source interface {
+ Publish() error
+}
diff --git a/resources/resource/resourcetypes.go b/resources/resource/resourcetypes.go
new file mode 100644
index 000000000..120d753e4
--- /dev/null
+++ b/resources/resource/resourcetypes.go
@@ -0,0 +1,106 @@
+// Copyright 2019 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package resource
+
+import (
+ "github.com/gohugoio/hugo/media"
+
+ "github.com/gohugoio/hugo/common/hugio"
+)
+
+// Cloner is an internal template and not meant for use in the templates. It
+// may change without notice.
+type Cloner interface {
+ WithNewBase(base string) Resource
+}
+
+// Resource represents a linkable resource, i.e. a content page, image etc.
+type Resource interface {
+ resourceBase
+
+ // Permalink represents the absolute link to this resource.
+ Permalink() string
+
+ // RelPermalink represents the host relative link to this resource.
+ RelPermalink() string
+
+ // ResourceType is the resource type. For most file types, this is the main
+ // part of the MIME type, e.g. "image", "application", "text" etc.
+ // For content pages, this value is "page".
+ ResourceType() string
+
+ // Name is the logical name of this resource. This can be set in the front matter
+ // metadata for this resource. If not set, Hugo will assign a value.
+ // This will in most cases be the base filename.
+ // So, for the image "/some/path/sunset.jpg" this will be "sunset.jpg".
+ // The value returned by this method will be used in the GetByPrefix and ByPrefix methods
+ // on Resources.
+ Name() string
+
+ // Title returns the title if set in front matter. For content pages, this will be the expected value.
+ Title() string
+
+ // Resource specific data set by Hugo.
+ // One example would be.Data.Digest for fingerprinted resources.
+ Data() interface{}
+
+ // Params set in front matter for this resource.
+ Params() map[string]interface{}
+}
+
+// resourceBase pulls out the minimal set of operations to define a Resource,
+// to simplify testing etc.
+type resourceBase interface {
+ // MediaType is this resource's MIME type.
+ MediaType() media.Type
+}
+
+// ResourcesLanguageMerger describes an interface for merging resources from a
+// different language.
+type ResourcesLanguageMerger interface {
+ MergeByLanguage(other Resources) Resources
+ // Needed for integration with the tpl package.
+ MergeByLanguageInterface(other interface{}) (interface{}, error)
+}
+
+// Identifier identifies a resource.
+type Identifier interface {
+ Key() string
+}
+
+// ContentResource represents a Resource that provides a way to get to its content.
+// Most Resource types in Hugo implements this interface, including Page.
+// This should be used with care, as it will read the file content into memory, but it
+// should be cached as effectively as possible by the implementation.
+type ContentResource interface {
+ resourceBase
+
+ // Content returns this resource's content. It will be equivalent to reading the content
+ // that RelPermalink points to in the published folder.
+ // The return type will be contextual, and should be what you would expect:
+ // * Page: template.HTML
+ // * JSON: String
+ // * Etc.
+ Content() (interface{}, error)
+}
+
+// OpenReadSeekCloser allows setting some other way (than reading from a filesystem)
+// to open or create a ReadSeekCloser.
+type OpenReadSeekCloser func() (hugio.ReadSeekCloser, error)
+
+// ReadSeekCloserResource is a Resource that supports loading its content.
+type ReadSeekCloserResource interface {
+ resourceBase
+ ReadSeekCloser() (hugio.ReadSeekCloser, error)
+}