aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--deps/deps.go8
-rw-r--r--hugolib/collections.go2
-rw-r--r--hugolib/page.go2
-rw-r--r--hugolib/page_output.go2
-rw-r--r--hugolib/page_resource.go2
-rw-r--r--hugolib/pagebundler_handlers.go7
-rw-r--r--hugolib/pages_language_merge_test.go2
-rw-r--r--hugolib/resource_chain_test.go2
-rw-r--r--hugolib/site.go4
-rw-r--r--resources/image.go (renamed from resource/image.go)14
-rw-r--r--resources/image_cache.go (renamed from resource/image_cache.go)4
-rw-r--r--resources/image_test.go (renamed from resource/image_test.go)4
-rw-r--r--resources/internal/glob.go48
-rw-r--r--resources/resource.go (renamed from resource/resource.go)266
-rw-r--r--resources/resource/resources.go123
-rw-r--r--resources/resource/resourcetypes.go106
-rw-r--r--resources/resource_cache.go (renamed from resource/resource_cache.go)18
-rw-r--r--resources/resource_factories/bundler/bundler.go (renamed from resource/resource_factories/bundler/bundler.go)19
-rw-r--r--resources/resource_factories/create/create.go (renamed from resource/resource_factories/create/create.go)17
-rw-r--r--resources/resource_metadata.go (renamed from resource/resource_metadata.go)11
-rw-r--r--resources/resource_metadata_test.go (renamed from resource/resource_metadata_test.go)11
-rw-r--r--resources/resource_test.go (renamed from resource/resource_test.go)22
-rw-r--r--resources/resource_transformers/integrity/integrity.go (renamed from resource/resource_transformers/integrity/integrity.go)13
-rw-r--r--resources/resource_transformers/minifier/minify.go (renamed from resource/resource_transformers/minifier/minify.go)15
-rw-r--r--resources/resource_transformers/postcss/postcss.go (renamed from resource/resource_transformers/postcss/postcss.go)15
-rw-r--r--resources/resource_transformers/templates/execute_as_template.go (renamed from resource/resource_transformers/templates/execute_as_template.go)15
-rw-r--r--resources/resource_transformers/tocss/scss/client.go (renamed from resource/resource_transformers/tocss/scss/client.go)12
-rw-r--r--resources/resource_transformers/tocss/scss/tocss.go (renamed from resource/resource_transformers/tocss/scss/tocss.go)4
-rw-r--r--resources/resource_transformers/tocss/scss/tocss_notavailable.go (renamed from resource/resource_transformers/tocss/scss/tocss_notavailable.go)4
-rw-r--r--resources/smartcrop.go (renamed from resource/smartcrop.go)4
-rw-r--r--resources/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg (renamed from resource/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg)bin90587 -> 90587 bytes
-rw-r--r--resources/testdata/circle.svg (renamed from resource/testdata/circle.svg)0
-rw-r--r--resources/testdata/gohugoio.png (renamed from resource/testdata/gohugoio.png)bin73886 -> 73886 bytes
-rw-r--r--resources/testdata/sub/gohugoio2.png (renamed from resource/testdata/sub/gohugoio2.png)bin73886 -> 73886 bytes
-rw-r--r--resources/testdata/sunset.jpg (renamed from resource/testdata/sunset.jpg)bin90587 -> 90587 bytes
-rw-r--r--resources/testhelpers_test.go (renamed from resource/testhelpers_test.go)7
-rw-r--r--resources/transform.go (renamed from resource/transform.go)25
-rw-r--r--resources/transform_test.go (renamed from resource/transform_test.go)4
-rw-r--r--tpl/resources/resources.go18
-rw-r--r--tpl/transform/unmarshal.go4
-rw-r--r--tpl/transform/unmarshal_test.go4
41 files changed, 461 insertions, 377 deletions
diff --git a/deps/deps.go b/deps/deps.go
index 7fba0e153..628019961 100644
--- a/deps/deps.go
+++ b/deps/deps.go
@@ -16,7 +16,7 @@ import (
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/metrics"
"github.com/gohugoio/hugo/output"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/tpl"
jww "github.com/spf13/jwalterweatherman"
@@ -52,7 +52,7 @@ type Deps struct {
SourceSpec *source.SourceSpec `json:"-"`
// The Resource Spec to use
- ResourceSpec *resource.Spec
+ ResourceSpec *resources.Spec
// The configuration to use
Cfg config.Provider `json:"-"`
@@ -214,7 +214,7 @@ func New(cfg DepsCfg) (*Deps, error) {
return nil, errors.WithMessage(err, "failed to create file caches from configuration")
}
- resourceSpec, err := resource.NewSpec(ps, fileCaches, logger, cfg.OutputFormats, cfg.MediaTypes)
+ resourceSpec, err := resources.NewSpec(ps, fileCaches, logger, cfg.OutputFormats, cfg.MediaTypes)
if err != nil {
return nil, err
}
@@ -281,7 +281,7 @@ func (d Deps) ForLanguage(cfg DepsCfg, onCreated func(d *Deps) error) (*Deps, er
// The resource cache is global so reuse.
// TODO(bep) clean up these inits.
resourceCache := d.ResourceSpec.ResourceCache
- d.ResourceSpec, err = resource.NewSpec(d.PathSpec, d.ResourceSpec.FileCaches, d.Log, cfg.OutputFormats, cfg.MediaTypes)
+ d.ResourceSpec, err = resources.NewSpec(d.PathSpec, d.ResourceSpec.FileCaches, d.Log, cfg.OutputFormats, cfg.MediaTypes)
if err != nil {
return nil, err
}
diff --git a/hugolib/collections.go b/hugolib/collections.go
index b9992c425..cf75d3732 100644
--- a/hugolib/collections.go
+++ b/hugolib/collections.go
@@ -16,7 +16,7 @@ package hugolib
import (
"fmt"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/gohugoio/hugo/common/collections"
)
diff --git a/hugolib/page.go b/hugolib/page.go
index 9f09dc9bd..71070d1e8 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -35,7 +35,7 @@ import (
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugolib/pagemeta"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/gohugoio/hugo/output"
"github.com/mitchellh/mapstructure"
diff --git a/hugolib/page_output.go b/hugolib/page_output.go
index 9a6531207..0a3eef9a6 100644
--- a/hugolib/page_output.go
+++ b/hugolib/page_output.go
@@ -24,7 +24,7 @@ import (
"github.com/gohugoio/hugo/tpl"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/gohugoio/hugo/media"
diff --git a/hugolib/page_resource.go b/hugolib/page_resource.go
index 808a692da..201076e8b 100644
--- a/hugolib/page_resource.go
+++ b/hugolib/page_resource.go
@@ -14,7 +14,7 @@
package hugolib
import (
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
)
var (
diff --git a/hugolib/pagebundler_handlers.go b/hugolib/pagebundler_handlers.go
index fdff76e24..2df1f8765 100644
--- a/hugolib/pagebundler_handlers.go
+++ b/hugolib/pagebundler_handlers.go
@@ -22,7 +22,8 @@ import (
"strings"
"github.com/gohugoio/hugo/helpers"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
)
var (
@@ -255,7 +256,7 @@ func (c *contentHandlers) parsePage(h contentHandler) contentHandler {
// Assign metadata from front matter if set
if len(p.resourcesMetadata) > 0 {
- resource.AssignMetadata(p.resourcesMetadata, p.Resources...)
+ resources.AssignMetadata(p.resourcesMetadata, p.Resources...)
}
}
@@ -309,7 +310,7 @@ func (c *contentHandlers) createResource() contentHandler {
}
resource, err := c.s.ResourceSpec.New(
- resource.ResourceSourceDescriptor{
+ resources.ResourceSourceDescriptor{
TargetPathBuilder: ctx.parentPage.subResourceTargetPathFactory,
SourceFile: ctx.source,
RelTargetFilename: ctx.target,
diff --git a/hugolib/pages_language_merge_test.go b/hugolib/pages_language_merge_test.go
index 6706af3bc..efcfbf04b 100644
--- a/hugolib/pages_language_merge_test.go
+++ b/hugolib/pages_language_merge_test.go
@@ -17,7 +17,7 @@ import (
"fmt"
"testing"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/stretchr/testify/require"
)
diff --git a/hugolib/resource_chain_test.go b/hugolib/resource_chain_test.go
index 0fe9c70c1..f53ab4966 100644
--- a/hugolib/resource_chain_test.go
+++ b/hugolib/resource_chain_test.go
@@ -25,7 +25,7 @@ import (
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/common/loggers"
- "github.com/gohugoio/hugo/resource/resource_transformers/tocss/scss"
+ "github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
)
func TestSCSSWithIncludePaths(t *testing.T) {
diff --git a/hugolib/site.go b/hugolib/site.go
index 9c225b332..43b398b70 100644
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -39,7 +39,6 @@ import (
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/publisher"
- "github.com/gohugoio/hugo/resource"
_errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/langs"
@@ -62,6 +61,7 @@ import (
"github.com/gohugoio/hugo/hugolib/pagemeta"
"github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/related"
+ "github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/tpl"
"github.com/spf13/afero"
@@ -760,7 +760,7 @@ func (s *Site) processPartial(events []fsnotify.Event) (whatChanged, error) {
cachePartitions := make([]string, len(events))
for i, ev := range events {
- cachePartitions[i] = resource.ResourceKeyPartition(ev.Name)
+ cachePartitions[i] = resources.ResourceKeyPartition(ev.Name)
if s.isContentDirEvent(ev) {
logger.Println("Source changed", ev)
diff --git a/resource/image.go b/resources/image.go
index 6dea4cbb8..d46facac5 100644
--- a/resource/image.go
+++ b/resources/image.go
@@ -1,4 +1,4 @@
-// Copyright 2017-present The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"errors"
@@ -27,6 +27,8 @@ import (
"strings"
"sync"
+ "github.com/gohugoio/hugo/resources/resource"
+
_errors "github.com/pkg/errors"
"github.com/disintegration/imaging"
@@ -43,9 +45,9 @@ import (
)
var (
- _ Resource = (*Image)(nil)
- _ Source = (*Image)(nil)
- _ Cloner = (*Image)(nil)
+ _ resource.Resource = (*Image)(nil)
+ _ resource.Source = (*Image)(nil)
+ _ resource.Cloner = (*Image)(nil)
)
// Imaging contains default image processing configuration. This will be fetched
@@ -146,7 +148,7 @@ func (i *Image) Height() int {
}
// WithNewBase implements the Cloner interface.
-func (i *Image) WithNewBase(base string) Resource {
+func (i *Image) WithNewBase(base string) resource.Resource {
return &Image{
imaging: i.imaging,
format: i.format,
diff --git a/resource/image_cache.go b/resources/image_cache.go
index 8cc626caf..58be839b3 100644
--- a/resource/image_cache.go
+++ b/resources/image_cache.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"fmt"
diff --git a/resource/image_test.go b/resources/image_test.go
index 07eab5d56..ffa482296 100644
--- a/resource/image_test.go
+++ b/resources/image_test.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"fmt"
diff --git a/resources/internal/glob.go b/resources/internal/glob.go
new file mode 100644
index 000000000..a87a23f13
--- /dev/null
+++ b/resources/internal/glob.go
@@ -0,0 +1,48 @@
+// 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 internal
+
+import (
+ "strings"
+ "sync"
+
+ "github.com/gobwas/glob"
+)
+
+var (
+ globCache = make(map[string]glob.Glob)
+ globMu sync.RWMutex
+)
+
+func GetGlob(pattern string) (glob.Glob, error) {
+ var g glob.Glob
+
+ globMu.RLock()
+ g, found := globCache[pattern]
+ globMu.RUnlock()
+ if !found {
+ var err error
+ g, err = glob.Compile(strings.ToLower(pattern), '/')
+ if err != nil {
+ return nil, err
+ }
+
+ globMu.Lock()
+ globCache[pattern] = g
+ globMu.Unlock()
+ }
+
+ return g, nil
+
+}
diff --git a/resource/resource.go b/resources/resource.go
index 0f5a43648..742903e80 100644
--- a/resource/resource.go
+++ b/resources/resource.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"fmt"
@@ -24,6 +24,8 @@ import (
"strings"
"sync"
+ "github.com/gohugoio/hugo/media"
+
"github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/tpl"
"github.com/pkg/errors"
@@ -32,35 +34,28 @@ import (
"github.com/gohugoio/hugo/common/collections"
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/common/loggers"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/spf13/afero"
- "github.com/gobwas/glob"
"github.com/gohugoio/hugo/helpers"
- "github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/source"
)
var (
- _ ContentResource = (*genericResource)(nil)
- _ ReadSeekCloserResource = (*genericResource)(nil)
- _ Resource = (*genericResource)(nil)
- _ Source = (*genericResource)(nil)
- _ Cloner = (*genericResource)(nil)
- _ ResourcesLanguageMerger = (*Resources)(nil)
- _ permalinker = (*genericResource)(nil)
- _ collections.Slicer = (*genericResource)(nil)
- _ Identifier = (*genericResource)(nil)
+ _ resource.ContentResource = (*genericResource)(nil)
+ _ resource.ReadSeekCloserResource = (*genericResource)(nil)
+ _ resource.Resource = (*genericResource)(nil)
+ _ resource.Source = (*genericResource)(nil)
+ _ resource.Cloner = (*genericResource)(nil)
+ _ resource.ResourcesLanguageMerger = (*resource.Resources)(nil)
+ _ permalinker = (*genericResource)(nil)
+ _ collections.Slicer = (*genericResource)(nil)
+ _ resource.Identifier = (*genericResource)(nil)
)
var noData = make(map[string]interface{})
-// Source is an internal template and not meant for use in the templates. It
-// may change without notice.
-type Source interface {
- Publish() error
-}
-
type permalinker interface {
relPermalinkFor(target string) string
permalinkFor(target string) string
@@ -69,215 +64,6 @@ type permalinker interface {
targetPath() string
}
-// 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)
-}
-
-type translatedResource interface {
- TranslationKey() string
-}
-
-// 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)
-}
-
-// 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 := 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 := 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
-}
-
-var (
- globCache = make(map[string]glob.Glob)
- globMu sync.RWMutex
-)
-
-func getGlob(pattern string) (glob.Glob, error) {
- var g glob.Glob
-
- globMu.RLock()
- g, found := globCache[pattern]
- globMu.RUnlock()
- if !found {
- var err error
- g, err = glob.Compile(strings.ToLower(pattern), '/')
- if err != nil {
- return nil, err
- }
-
- globMu.Lock()
- globCache[pattern] = g
- globMu.Unlock()
- }
-
- return g, nil
-
-}
-
-// 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
-}
-
type Spec struct {
*helpers.PathSpec
@@ -336,7 +122,7 @@ type ResourceSourceDescriptor struct {
// Need one of these to load the resource content.
SourceFile source.File
- OpenReadSeekCloser OpenReadSeekCloser
+ OpenReadSeekCloser resource.OpenReadSeekCloser
// If OpenReadSeekerCloser is not set, we use this to open the file.
SourceFilename string
@@ -370,15 +156,15 @@ func (r *Spec) sourceFs() afero.Fs {
return r.PathSpec.BaseFs.Content.Fs
}
-func (r *Spec) New(fd ResourceSourceDescriptor) (Resource, error) {
+func (r *Spec) New(fd ResourceSourceDescriptor) (resource.Resource, error) {
return r.newResourceForFs(r.sourceFs(), fd)
}
-func (r *Spec) NewForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Resource, error) {
+func (r *Spec) NewForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) {
return r.newResourceForFs(sourceFs, fd)
}
-func (r *Spec) newResourceForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Resource, error) {
+func (r *Spec) newResourceForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) {
if fd.OpenReadSeekCloser == nil {
if fd.SourceFile != nil && fd.SourceFilename != "" {
return nil, errors.New("both SourceFile and AbsSourceFilename provided")
@@ -399,7 +185,7 @@ func (r *Spec) newResourceForFs(sourceFs afero.Fs, fd ResourceSourceDescriptor)
return r.newResource(sourceFs, fd)
}
-func (r *Spec) newResource(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Resource, error) {
+func (r *Spec) newResource(sourceFs afero.Fs, fd ResourceSourceDescriptor) (resource.Resource, error) {
var fi os.FileInfo
var sourceFilename string
@@ -551,7 +337,7 @@ type publishOnce struct {
logger *loggers.Logger
}
-func (l *publishOnce) publish(s Source) error {
+func (l *publishOnce) publish(s resource.Source) error {
l.publisherInit.Do(func() {
l.publisherErr = s.Publish()
if l.publisherErr != nil {
@@ -577,7 +363,7 @@ type genericResource struct {
sourceFilename string
// Will be set if this resource is backed by something other than a file.
- openReadSeekerCloser OpenReadSeekCloser
+ openReadSeekerCloser resource.OpenReadSeekCloser
// A hash of the source content. Is only calculated in caching situations.
*resourceHash
@@ -632,7 +418,7 @@ func (l *genericResource) MediaType() media.Type {
}
// Implement the Cloner interface.
-func (l genericResource) WithNewBase(base string) Resource {
+func (l genericResource) WithNewBase(base string) resource.Resource {
l.baseOffset = base
l.resourceContent = &resourceContent{}
return &l
@@ -642,12 +428,12 @@ func (l genericResource) WithNewBase(base string) Resource {
// for the template functions. See collections.Slice.
func (commonResource) Slice(in interface{}) (interface{}, error) {
switch items := in.(type) {
- case Resources:
+ case resource.Resources:
return items, nil
case []interface{}:
- groups := make(Resources, len(items))
+ groups := make(resource.Resources, len(items))
for i, v := range items {
- g, ok := v.(Resource)
+ g, ok := v.(resource.Resource)
if !ok {
return nil, fmt.Errorf("type %T is not a Resource", v)
}
@@ -903,7 +689,7 @@ func (r *Spec) newGenericResource(sourceFs afero.Fs,
func (r *Spec) newGenericResourceWithBase(
sourceFs afero.Fs,
lazyPublish bool,
- openReadSeekerCloser OpenReadSeekCloser,
+ openReadSeekerCloser resource.OpenReadSeekCloser,
urlBaseDir string,
targetPathBaseDirs []string,
targetPathBuilder func(base string) string,
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)
+}
diff --git a/resource/resource_cache.go b/resources/resource_cache.go
index e7c6ab6d0..8ff63beb0 100644
--- a/resource/resource_cache.go
+++ b/resources/resource_cache.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"encoding/json"
@@ -21,6 +21,8 @@ import (
"strings"
"sync"
+ "github.com/gohugoio/hugo/resources/resource"
+
"github.com/gohugoio/hugo/cache/filecache"
"github.com/BurntSushi/locker"
@@ -35,7 +37,7 @@ type ResourceCache struct {
rs *Spec
sync.RWMutex
- cache map[string]Resource
+ cache map[string]resource.Resource
fileCache *filecache.Cache
@@ -59,7 +61,7 @@ func newResourceCache(rs *Spec) *ResourceCache {
return &ResourceCache{
rs: rs,
fileCache: rs.FileCaches.AssetsCache(),
- cache: make(map[string]Resource),
+ cache: make(map[string]resource.Resource),
nlocker: locker.NewLocker(),
}
}
@@ -68,7 +70,7 @@ func (c *ResourceCache) clear() {
c.Lock()
defer c.Unlock()
- c.cache = make(map[string]Resource)
+ c.cache = make(map[string]resource.Resource)
c.nlocker = locker.NewLocker()
}
@@ -82,14 +84,14 @@ func (c *ResourceCache) cleanKey(key string) string {
return strings.TrimPrefix(path.Clean(key), "/")
}
-func (c *ResourceCache) get(key string) (Resource, bool) {
+func (c *ResourceCache) get(key string) (resource.Resource, bool) {
c.RLock()
defer c.RUnlock()
r, found := c.cache[key]
return r, found
}
-func (c *ResourceCache) GetOrCreate(partition, key string, f func() (Resource, error)) (Resource, error) {
+func (c *ResourceCache) GetOrCreate(partition, key string, f func() (resource.Resource, error)) (resource.Resource, error) {
key = c.cleanKey(path.Join(partition, key))
// First check in-memory cache.
r, found := c.get(key)
@@ -172,7 +174,7 @@ func (c *ResourceCache) writeMeta(key string, meta transformedResourceMetadata)
}
-func (c *ResourceCache) set(key string, r Resource) {
+func (c *ResourceCache) set(key string, r resource.Resource) {
c.Lock()
defer c.Unlock()
c.cache[key] = r
diff --git a/resource/resource_factories/bundler/bundler.go b/resources/resource_factories/bundler/bundler.go
index 70b8ee536..ca0ccf86e 100644
--- a/resource/resource_factories/bundler/bundler.go
+++ b/resources/resource_factories/bundler/bundler.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -21,17 +21,18 @@ import (
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/media"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
)
// Client contains methods perform concatenation and other bundling related
// tasks to Resource objects.
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
}
// New creates a new Client with the given specification.
-func New(rs *resource.Spec) *Client {
+func New(rs *resources.Spec) *Client {
return &Client{rs: rs}
}
@@ -62,14 +63,14 @@ func (r *multiReadSeekCloser) Close() error {
}
// Concat concatenates the list of Resource objects.
-func (c *Client) Concat(targetPath string, resources resource.Resources) (resource.Resource, error) {
+func (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resource, error) {
// The CACHE_OTHER will make sure this will be re-created and published on rebuilds.
- return c.rs.ResourceCache.GetOrCreate(resource.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
+ return c.rs.ResourceCache.GetOrCreate(resources.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
var resolvedm media.Type
// The given set of resources must be of the same Media Type.
// We may improve on that in the future, but then we need to know more.
- for i, r := range resources {
+ for i, r := range r {
if i > 0 && r.MediaType().Type() != resolvedm.Type() {
return nil, fmt.Errorf("resources in Concat must be of the same Media Type, got %q and %q", r.MediaType().Type(), resolvedm.Type())
}
@@ -78,7 +79,7 @@ func (c *Client) Concat(targetPath string, resources resource.Resources) (resour
concatr := func() (hugio.ReadSeekCloser, error) {
var rcsources []hugio.ReadSeekCloser
- for _, s := range resources {
+ for _, s := range r {
rcr, ok := s.(resource.ReadSeekCloserResource)
if !ok {
return nil, fmt.Errorf("resource %T does not implement resource.ReadSeekerCloserResource", s)
@@ -106,7 +107,7 @@ func (c *Client) Concat(targetPath string, resources resource.Resources) (resour
composite, err := c.rs.NewForFs(
c.rs.FileCaches.AssetsCache().Fs,
- resource.ResourceSourceDescriptor{
+ resources.ResourceSourceDescriptor{
LazyPublish: true,
OpenReadSeekCloser: concatr,
RelTargetFilename: filepath.Clean(targetPath)})
diff --git a/resource/resource_factories/create/create.go b/resources/resource_factories/create/create.go
index db23930e4..dc565056d 100644
--- a/resource/resource_factories/create/create.go
+++ b/resources/resource_factories/create/create.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -21,26 +21,27 @@ import (
"github.com/spf13/afero"
"github.com/gohugoio/hugo/common/hugio"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
)
// Client contains methods to create Resource objects.
// tasks to Resource objects.
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
}
// New creates a new Client with the given specification.
-func New(rs *resource.Spec) *Client {
+func New(rs *resources.Spec) *Client {
return &Client{rs: rs}
}
// Get creates a new Resource by opening the given filename in the given filesystem.
func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
filename = filepath.Clean(filename)
- return c.rs.ResourceCache.GetOrCreate(resource.ResourceKeyPartition(filename), filename, func() (resource.Resource, error) {
+ return c.rs.ResourceCache.GetOrCreate(resources.ResourceKeyPartition(filename), filename, func() (resource.Resource, error) {
return c.rs.NewForFs(fs,
- resource.ResourceSourceDescriptor{
+ resources.ResourceSourceDescriptor{
LazyPublish: true,
SourceFilename: filename})
})
@@ -49,10 +50,10 @@ func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
// FromString creates a new Resource from a string with the given relative target path.
func (c *Client) FromString(targetPath, content string) (resource.Resource, error) {
- return c.rs.ResourceCache.GetOrCreate(resource.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
+ return c.rs.ResourceCache.GetOrCreate(resources.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
return c.rs.NewForFs(
c.rs.FileCaches.AssetsCache().Fs,
- resource.ResourceSourceDescriptor{
+ resources.ResourceSourceDescriptor{
LazyPublish: true,
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
return hugio.NewReadSeekerNoOpCloserFromString(content), nil
diff --git a/resource/resource_metadata.go b/resources/resource_metadata.go
index 20c4f130b..0830dfc59 100644
--- a/resource/resource_metadata.go
+++ b/resources/resource_metadata.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,12 +11,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"fmt"
"strconv"
+ "github.com/gohugoio/hugo/resources/internal"
+ "github.com/gohugoio/hugo/resources/resource"
+
"github.com/pkg/errors"
"github.com/spf13/cast"
@@ -43,7 +46,7 @@ const counterPlaceHolder = ":counter"
// This assignment is additive, but the most specific match needs to be first.
// The `name` and `title` metadata field support shell-matched collection it got a match in.
// See https://golang.org/pkg/path/#Match
-func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) error {
+func AssignMetadata(metadata []map[string]interface{}, resources ...resource.Resource) error {
counters := make(map[string]int)
@@ -68,7 +71,7 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
srcKey := strings.ToLower(cast.ToString(src))
- glob, err := getGlob(srcKey)
+ glob, err := internal.GetGlob(srcKey)
if err != nil {
return errors.Wrap(err, "failed to match resource with metadata")
}
diff --git a/resource/resource_metadata_test.go b/resources/resource_metadata_test.go
index 85fb25b57..a1a2a738c 100644
--- a/resource/resource_metadata_test.go
+++ b/resources/resource_metadata_test.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,12 +11,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"testing"
"github.com/gohugoio/hugo/media"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/stretchr/testify/require"
)
@@ -25,8 +26,8 @@ func TestAssignMetadata(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
- var foo1, foo2, foo3, logo1, logo2, logo3 Resource
- var resources Resources
+ var foo1, foo2, foo3, logo1, logo2, logo3 resource.Resource
+ var resources resource.Resources
for _, this := range []struct {
metaData []map[string]interface{}
@@ -215,7 +216,7 @@ func TestAssignMetadata(t *testing.T) {
foo3 = spec.newGenericResource(nil, nil, nil, "/b/foo3.css", "foo3.css", media.CSSType)
logo3 = spec.newGenericResource(nil, nil, nil, "/b/logo3.png", "logo3.png", pngType)
- resources = Resources{
+ resources = resource.Resources{
foo2,
logo2,
foo1,
diff --git a/resource/resource_test.go b/resources/resource_test.go
index b3f6035b6..be2706e45 100644
--- a/resource/resource_test.go
+++ b/resources/resource_test.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"fmt"
@@ -22,6 +22,8 @@ import (
"testing"
"time"
+ "github.com/gohugoio/hugo/resources/resource"
+
"github.com/gohugoio/hugo/media"
"github.com/stretchr/testify/require"
@@ -75,7 +77,7 @@ func TestNewResourceFromFilename(t *testing.T) {
assert.NotNil(r)
assert.Equal("json", r.ResourceType())
- cloned := r.(Cloner).WithNewBase("aceof")
+ cloned := r.(resource.Cloner).WithNewBase("aceof")
assert.Equal(r.ResourceType(), cloned.ResourceType())
assert.Equal("/aceof/a/b/data.json", cloned.RelPermalink())
}
@@ -103,7 +105,7 @@ var pngType, _ = media.FromStringAndExt("image/png", "png")
func TestResourcesByType(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
- resources := Resources{
+ resources := resource.Resources{
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
spec.newGenericResource(nil, nil, nil, "/a/logo.png", "logo.css", pngType),
spec.newGenericResource(nil, nil, nil, "/a/foo2.css", "foo2.css", media.CSSType),
@@ -117,7 +119,7 @@ func TestResourcesByType(t *testing.T) {
func TestResourcesGetByPrefix(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
- resources := Resources{
+ resources := resource.Resources{
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType),
spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType),
@@ -146,7 +148,7 @@ func TestResourcesGetByPrefix(t *testing.T) {
func TestResourcesGetMatch(t *testing.T) {
assert := require.New(t)
spec := newTestResourceSpec(assert)
- resources := Resources{
+ resources := resource.Resources{
spec.newGenericResource(nil, nil, nil, "/a/foo1.css", "foo1.css", media.CSSType),
spec.newGenericResource(nil, nil, nil, "/a/logo1.png", "logo1.png", pngType),
spec.newGenericResource(nil, nil, nil, "/b/Logo2.png", "Logo2.png", pngType),
@@ -211,7 +213,7 @@ func BenchmarkResourcesMatchA100(b *testing.B) {
a100 := strings.Repeat("a", 100)
pattern := "a*a*a*a*a*a*a*a*b"
- resources := Resources{spec.newGenericResource(nil, nil, nil, "/a/"+a100, a100, media.CSSType)}
+ resources := resource.Resources{spec.newGenericResource(nil, nil, nil, "/a/"+a100, a100, media.CSSType)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -220,10 +222,10 @@ func BenchmarkResourcesMatchA100(b *testing.B) {
}
-func benchResources(b *testing.B) Resources {
+func benchResources(b *testing.B) resource.Resources {
assert := require.New(b)
spec := newTestResourceSpec(assert)
- var resources Resources
+ var resources resource.Resources
for i := 0; i < 30; i++ {
name := fmt.Sprintf("abcde%d_%d.css", i%5, i)
@@ -250,7 +252,7 @@ func BenchmarkAssignMetadata(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
- var resources Resources
+ var resources resource.Resources
var meta = []map[string]interface{}{
{
"title": "Foo #:counter",
diff --git a/resource/resource_transformers/integrity/integrity.go b/resources/resource_transformers/integrity/integrity.go
index 535c06a32..90afafb88 100644
--- a/resource/resource_transformers/integrity/integrity.go
+++ b/resources/resource_transformers/integrity/integrity.go
@@ -24,7 +24,8 @@ import (
"html/template"
"io"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
)
const defaultHashAlgo = "sha256"
@@ -32,11 +33,11 @@ const defaultHashAlgo = "sha256"
// Client contains methods to fingerprint (cachebusting) and other integrity-related
// methods.
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
}
// New creates a new Client with the given specification.
-func New(rs *resource.Spec) *Client {
+func New(rs *resources.Spec) *Client {
return &Client{rs: rs}
}
@@ -44,13 +45,13 @@ type fingerprintTransformation struct {
algo string
}
-func (t *fingerprintTransformation) Key() resource.ResourceTransformationKey {
- return resource.NewResourceTransformationKey("fingerprint", t.algo)
+func (t *fingerprintTransformation) Key() resources.ResourceTransformationKey {
+ return resources.NewResourceTransformationKey("fingerprint", t.algo)
}
// Transform creates a MD5 hash of the Resource content and inserts that hash before
// the extension in the filename.
-func (t *fingerprintTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
+func (t *fingerprintTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
algo := t.algo
var h hash.Hash
diff --git a/resource/resource_transformers/minifier/minify.go b/resources/resource_transformers/minifier/minify.go
index cef22efc0..952c6a99c 100644
--- a/resource/resource_transformers/minifier/minify.go
+++ b/resources/resource_transformers/minifier/minify.go
@@ -15,32 +15,33 @@ package minifier
import (
"github.com/gohugoio/hugo/minifiers"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
)
// Client for minification of Resource objects. Supported minfiers are:
// css, html, js, json, svg and xml.
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
m minifiers.Client
}
// New creates a new Client given a specification. Note that it is the media types
// configured for the site that is used to match files to the correct minifier.
-func New(rs *resource.Spec) *Client {
+func New(rs *resources.Spec) *Client {
return &Client{rs: rs, m: minifiers.New(rs.MediaTypes, rs.OutputFormats)}
}
type minifyTransformation struct {
- rs *resource.Spec
+ rs *resources.Spec
m minifiers.Client
}
-func (t *minifyTransformation) Key() resource.ResourceTransformationKey {
- return resource.NewResourceTransformationKey("minify")
+func (t *minifyTransformation) Key() resources.ResourceTransformationKey {
+ return resources.NewResourceTransformationKey("minify")
}
-func (t *minifyTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
+func (t *minifyTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
if err := t.m.Minify(ctx.InMediaType, ctx.To, ctx.From); err != nil {
return err
}
diff --git a/resource/resource_transformers/postcss/postcss.go b/resources/resource_transformers/postcss/postcss.go
index ec73543dd..5350eebc5 100644
--- a/resource/resource_transformers/postcss/postcss.go
+++ b/resources/resource_transformers/postcss/postcss.go
@@ -26,7 +26,8 @@ import (
"github.com/mitchellh/mapstructure"
"github.com/gohugoio/hugo/common/herrors"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
)
// Some of the options from https://github.com/postcss/postcss-cli
@@ -74,28 +75,28 @@ func (opts Options) toArgs() []string {
// Client is the client used to do PostCSS transformations.
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
}
// New creates a new Client with the given specification.
-func New(rs *resource.Spec) *Client {
+func New(rs *resources.Spec) *Client {
return &Client{rs: rs}
}
type postcssTransformation struct {
options Options
- rs *resource.Spec
+ rs *resources.Spec
}
-func (t *postcssTransformation) Key() resource.ResourceTransformationKey {
- return resource.NewResourceTransformationKey("postcss", t.options)
+func (t *postcssTransformation) Key() resources.ResourceTransformationKey {
+ return resources.NewResourceTransformationKey("postcss", t.options)
}
// Transform shells out to postcss-cli to do the heavy lifting.
// For this to work, you need some additional tools. To install them globally:
// npm install -g postcss-cli
// npm install -g autoprefixer
-func (t *postcssTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
+func (t *postcssTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
const localPostCSSPath = "node_modules/postcss-cli/bin/"
const binaryName = "postcss"
diff --git a/resource/resource_transformers/templates/execute_as_template.go b/resources/resource_transformers/templates/execute_as_template.go
index a126b26c9..b3ec3cf43 100644
--- a/resource/resource_transformers/templates/execute_as_template.go
+++ b/resources/resource_transformers/templates/execute_as_template.go
@@ -16,20 +16,21 @@ package templates
import (
"github.com/gohugoio/hugo/helpers"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/gohugoio/hugo/tpl"
"github.com/pkg/errors"
)
// Client contains methods to perform template processing of Resource objects.
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
textTemplate tpl.TemplateParseFinder
}
// New creates a new Client with the given specification.
-func New(rs *resource.Spec, textTemplate tpl.TemplateParseFinder) *Client {
+func New(rs *resources.Spec, textTemplate tpl.TemplateParseFinder) *Client {
if rs == nil {
panic("must provice a resource Spec")
}
@@ -40,17 +41,17 @@ func New(rs *resource.Spec, textTemplate tpl.TemplateParseFinder) *Client {
}
type executeAsTemplateTransform struct {
- rs *resource.Spec
+ rs *resources.Spec
textTemplate tpl.TemplateParseFinder
targetPath string
data interface{}
}
-func (t *executeAsTemplateTransform) Key() resource.ResourceTransformationKey {
- return resource.NewResourceTransformationKey("execute-as-template", t.targetPath)
+func (t *executeAsTemplateTransform) Key() resources.ResourceTransformationKey {
+ return resources.NewResourceTransformationKey("execute-as-template", t.targetPath)
}
-func (t *executeAsTemplateTransform) Transform(ctx *resource.ResourceTransformationCtx) error {
+func (t *executeAsTemplateTransform) Transform(ctx *resources.ResourceTransformationCtx) error {
tplStr := helpers.ReaderToString(ctx.From)
templ, err := t.textTemplate.Parse(ctx.InPath, tplStr)
if err != nil {
diff --git a/resource/resource_transformers/tocss/scss/client.go b/resources/resource_transformers/tocss/scss/client.go
index 126727e06..41ff67433 100644
--- a/resource/resource_transformers/tocss/scss/client.go
+++ b/resources/resource_transformers/tocss/scss/client.go
@@ -17,17 +17,19 @@ import (
"github.com/bep/go-tocss/scss"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugolib/filesystems"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
+ "github.com/gohugoio/hugo/resources/resource"
+
"github.com/mitchellh/mapstructure"
)
type Client struct {
- rs *resource.Spec
+ rs *resources.Spec
sfs *filesystems.SourceFilesystem
workFs *filesystems.SourceFilesystem
}
-func New(fs *filesystems.SourceFilesystem, rs *resource.Spec) (*Client, error) {
+func New(fs *filesystems.SourceFilesystem, rs *resources.Spec) (*Client, error) {
return &Client{sfs: fs, workFs: rs.BaseFs.Work, rs: rs}, nil
}
@@ -91,8 +93,8 @@ type toCSSTransformation struct {
options options
}
-func (t *toCSSTransformation) Key() resource.ResourceTransformationKey {
- return resource.NewResourceTransformationKey("tocss", t.options.from)
+func (t *toCSSTransformation) Key() resources.ResourceTransformationKey {
+ return resources.NewResourceTransformationKey("tocss", t.options.from)
}
func DecodeOptions(m map[string]interface{}) (opts Options, err error) {
diff --git a/resource/resource_transformers/tocss/scss/tocss.go b/resources/resource_transformers/tocss/scss/tocss.go
index 984e14fc2..17c32ea8e 100644
--- a/resource/resource_transformers/tocss/scss/tocss.go
+++ b/resources/resource_transformers/tocss/scss/tocss.go
@@ -28,7 +28,7 @@ import (
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/media"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
"github.com/pkg/errors"
)
@@ -37,7 +37,7 @@ func Supports() bool {
return true
}
-func (t *toCSSTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
+func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
ctx.OutMediaType = media.CSSType
var outName string
diff --git a/resource/resource_transformers/tocss/scss/tocss_notavailable.go b/resources/resource_transformers/tocss/scss/tocss_notavailable.go
index df918b368..ad6b42b98 100644
--- a/resource/resource_transformers/tocss/scss/tocss_notavailable.go
+++ b/resources/resource_transformers/tocss/scss/tocss_notavailable.go
@@ -17,7 +17,7 @@ package scss
import (
"github.com/gohugoio/hugo/common/herrors"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources"
)
// Used in tests.
@@ -25,6 +25,6 @@ func Supports() bool {
return false
}
-func (t *toCSSTransformation) Transform(ctx *resource.ResourceTransformationCtx) error {
+func (t *toCSSTransformation) Transform(ctx *resources.ResourceTransformationCtx) error {
return herrors.ErrFeatureNotAvailable
}
diff --git a/resource/smartcrop.go b/resources/smartcrop.go
index 201262436..05bc55cd7 100644
--- a/resource/smartcrop.go
+++ b/resources/smartcrop.go
@@ -1,4 +1,4 @@
-// Copyright 2017-present The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"image"
diff --git a/resource/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg b/resources/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg
index 7d7307bed..7d7307bed 100644
--- a/resource/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg
+++ b/resources/testdata/1234567890qwertyuiopasdfghjklzxcvbnm5to6eeeeee7via8eleph.jpg
Binary files differ
diff --git a/resource/testdata/circle.svg b/resources/testdata/circle.svg
index 2759ae703..2759ae703 100644
--- a/resource/testdata/circle.svg
+++ b/resources/testdata/circle.svg
diff --git a/resource/testdata/gohugoio.png b/resources/testdata/gohugoio.png
index 0591db959..0591db959 100644
--- a/resource/testdata/gohugoio.png
+++ b/resources/testdata/gohugoio.png
Binary files differ
diff --git a/resource/testdata/sub/gohugoio2.png b/resources/testdata/sub/gohugoio2.png
index 0591db959..0591db959 100644
--- a/resource/testdata/sub/gohugoio2.png
+++ b/resources/testdata/sub/gohugoio2.png
Binary files differ
diff --git a/resource/testdata/sunset.jpg b/resources/testdata/sunset.jpg
index 7d7307bed..7d7307bed 100644
--- a/resource/testdata/sunset.jpg
+++ b/resources/testdata/sunset.jpg
Binary files differ
diff --git a/resource/testhelpers_test.go b/resources/testhelpers_test.go
index 55833bafa..d0fcb59e7 100644
--- a/resource/testhelpers_test.go
+++ b/resources/testhelpers_test.go
@@ -1,4 +1,4 @@
-package resource
+package resources
import (
"path/filepath"
@@ -18,6 +18,7 @@ import (
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/output"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
@@ -112,7 +113,7 @@ func fetchImageForSpec(spec *Spec, assert *require.Assertions, name string) *Ima
return r.(*Image)
}
-func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) ContentResource {
+func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) resource.ContentResource {
src, err := os.Open(filepath.FromSlash("testdata/" + name))
assert.NoError(err)
@@ -130,7 +131,7 @@ func fetchResourceForSpec(spec *Spec, assert *require.Assertions, name string) C
r, err := spec.New(ResourceSourceDescriptor{TargetPathBuilder: factory, SourceFilename: name})
assert.NoError(err)
- return r.(ContentResource)
+ return r.(resource.ContentResource)
}
func assertImageFile(assert *require.Assertions, fs afero.Fs, filename string, width, height int) {
diff --git a/resource/transform.go b/resources/transform.go
index bd59d0658..fd3ae1ae6 100644
--- a/resource/transform.go
+++ b/resources/transform.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"bytes"
@@ -23,6 +23,7 @@ import (
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/helpers"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/mitchellh/hashstructure"
"fmt"
@@ -35,13 +36,13 @@ import (
)
var (
- _ ContentResource = (*transformedResource)(nil)
- _ ReadSeekCloserResource = (*transformedResource)(nil)
- _ collections.Slicer = (*transformedResource)(nil)
- _ Identifier = (*transformedResource)(nil)
+ _ resource.ContentResource = (*transformedResource)(nil)
+ _ resource.ReadSeekCloserResource = (*transformedResource)(nil)
+ _ collections.Slicer = (*transformedResource)(nil)
+ _ resource.Identifier = (*transformedResource)(nil)
)
-func (s *Spec) Transform(r Resource, t ResourceTransformation) (Resource, error) {
+func (s *Spec) Transform(r resource.Resource, t ResourceTransformation) (resource.Resource, error) {
return &transformedResource{
Resource: r,
transformation: t,
@@ -195,7 +196,7 @@ type transformedResource struct {
transformedResourceMetadata
// The source
- Resource
+ resource.Resource
}
func (r *transformedResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
@@ -292,11 +293,11 @@ func (r *transformedResource) transform(setContent, publish bool) (err error) {
// This can be the last resource in a chain.
// Rewind and create a processing chain.
- var chain []Resource
+ var chain []resource.Resource
current := r
for {
rr := current.Resource
- chain = append(chain[:0], append([]Resource{rr}, chain[0:]...)...)
+ chain = append(chain[:0], append([]resource.Resource{rr}, chain[0:]...)...)
if tr, ok := rr.(*transformedResource); ok {
current = tr
} else {
@@ -538,9 +539,9 @@ func (r *transformedResource) initTransform(setContent, publish bool) error {
}
// contentReadSeekerCloser returns a ReadSeekerCloser if possible for a given Resource.
-func contentReadSeekerCloser(r Resource) (hugio.ReadSeekCloser, error) {
+func contentReadSeekerCloser(r resource.Resource) (hugio.ReadSeekCloser, error) {
switch rr := r.(type) {
- case ReadSeekCloserResource:
+ case resource.ReadSeekCloserResource:
rc, err := rr.ReadSeekCloser()
if err != nil {
return nil, err
diff --git a/resource/transform_test.go b/resources/transform_test.go
index df68e780d..ed462cd2a 100644
--- a/resource/transform_test.go
+++ b/resources/transform_test.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package resource
+package resources
import (
"testing"
diff --git a/tpl/resources/resources.go b/tpl/resources/resources.go
index 497611b75..d32e12a05 100644
--- a/tpl/resources/resources.go
+++ b/tpl/resources/resources.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -22,14 +22,14 @@ import (
_errors "github.com/pkg/errors"
"github.com/gohugoio/hugo/deps"
- "github.com/gohugoio/hugo/resource"
- "github.com/gohugoio/hugo/resource/resource_factories/bundler"
- "github.com/gohugoio/hugo/resource/resource_factories/create"
- "github.com/gohugoio/hugo/resource/resource_transformers/integrity"
- "github.com/gohugoio/hugo/resource/resource_transformers/minifier"
- "github.com/gohugoio/hugo/resource/resource_transformers/postcss"
- "github.com/gohugoio/hugo/resource/resource_transformers/templates"
- "github.com/gohugoio/hugo/resource/resource_transformers/tocss/scss"
+ "github.com/gohugoio/hugo/resources/resource"
+ "github.com/gohugoio/hugo/resources/resource_factories/bundler"
+ "github.com/gohugoio/hugo/resources/resource_factories/create"
+ "github.com/gohugoio/hugo/resources/resource_transformers/integrity"
+ "github.com/gohugoio/hugo/resources/resource_transformers/minifier"
+ "github.com/gohugoio/hugo/resources/resource_transformers/postcss"
+ "github.com/gohugoio/hugo/resources/resource_transformers/templates"
+ "github.com/gohugoio/hugo/resources/resource_transformers/tocss/scss"
"github.com/spf13/cast"
)
diff --git a/tpl/transform/unmarshal.go b/tpl/transform/unmarshal.go
index c27a21a9e..da06b6aa1 100644
--- a/tpl/transform/unmarshal.go
+++ b/tpl/transform/unmarshal.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -21,7 +21,7 @@ import (
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/parser/metadecoders"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/pkg/errors"
"github.com/spf13/cast"
diff --git a/tpl/transform/unmarshal_test.go b/tpl/transform/unmarshal_test.go
index d9ebd1f89..1defe8c9c 100644
--- a/tpl/transform/unmarshal_test.go
+++ b/tpl/transform/unmarshal_test.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
+// 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.
@@ -23,7 +23,7 @@ import (
"github.com/gohugoio/hugo/media"
- "github.com/gohugoio/hugo/resource"
+ "github.com/gohugoio/hugo/resources/resource"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)