summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hugolib/page.go4
-rw-r--r--hugolib/resource_chain_test.go5
-rw-r--r--resources/errorResource.go129
-rw-r--r--resources/page/page_nop.go4
-rw-r--r--resources/page/testhelpers_test.go5
-rw-r--r--resources/resource.go4
-rw-r--r--resources/resource/resourcetypes.go1
-rw-r--r--resources/resource_factories/create/create.go2
-rw-r--r--resources/transform.go4
-rw-r--r--tpl/resources/resources.go44
10 files changed, 182 insertions, 20 deletions
diff --git a/hugolib/page.go b/hugolib/page.go
index ab2a4d74c..f35865cf0 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -129,6 +129,10 @@ type pageState struct {
*pageCommon
}
+func (p *pageState) Err() error {
+ return nil
+}
+
// Eq returns whether the current page equals the given page.
// This is what's invoked when doing `{{ if eq $page $otherPage }}`
func (p *pageState) Eq(other interface{}) bool {
diff --git a/hugolib/resource_chain_test.go b/hugolib/resource_chain_test.go
index efd28a95d..214dda216 100644
--- a/hugolib/resource_chain_test.go
+++ b/hugolib/resource_chain_test.go
@@ -415,6 +415,7 @@ CSS integrity Data last: {{ $cssFingerprinted2.RelPermalink }} {{ $cssFingerpri
{{ $rimg := resources.Get "%[1]s/sunset.jpg" }}
{{ $remotenotfound := resources.Get "%[1]s/notfound.jpg" }}
{{ $localnotfound := resources.Get "images/notfound.jpg" }}
+{{ $gopherprotocol := resources.Get "gopher://example.org" }}
{{ $rfit := $rimg.Fit "200x200" }}
{{ $rfit2 := $rfit.Fit "100x200" }}
{{ $rimg = $rimg | fingerprint }}
@@ -422,6 +423,8 @@ SUNSET REMOTE: {{ $rimg.Name }}|{{ $rimg.RelPermalink }}|{{ $rimg.Width }}|{{ le
FIT REMOTE: {{ $rfit.Name }}|{{ $rfit.RelPermalink }}|{{ $rfit.Width }}
REMOTE NOT FOUND: {{ if $remotenotfound }}FAILED{{ else}}OK{{ end }}
LOCAL NOT FOUND: {{ if $localnotfound }}FAILED{{ else}}OK{{ end }}
+PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ . | safeHTML }}{{ end }}
+PRINT PROTOCOL ERROR2: {{ with $gopherprotocol }}{{ .Err | safeHTML }}{{ end }}
`, ts.URL))
@@ -454,6 +457,8 @@ SUNSET REMOTE: sunset_%[1]s.jpg|/sunset_%[1]s.a9bf1d944e19c0f382e0d8f51de690f7d0
FIT REMOTE: sunset_%[1]s.jpg|/sunset_%[1]s_hu59e56ffff1bc1d8d122b1403d34e039f_0_200x200_fit_q75_box.jpg|200
REMOTE NOT FOUND: OK
LOCAL NOT FOUND: OK
+PRINT PROTOCOL ERROR1: error calling resources.Get: Get "gopher://example.org": unsupported protocol scheme "gopher"
+PRINT PROTOCOL ERROR2: error calling resources.Get: Get "gopher://example.org": unsupported protocol scheme "gopher"
`, helpers.HashString(ts.URL+"/sunset.jpg", map[string]interface{}{})))
diff --git a/resources/errorResource.go b/resources/errorResource.go
new file mode 100644
index 000000000..705547d4c
--- /dev/null
+++ b/resources/errorResource.go
@@ -0,0 +1,129 @@
+// Copyright 2021 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 resources
+
+import (
+ "image"
+
+ "github.com/gohugoio/hugo/common/hugio"
+ "github.com/gohugoio/hugo/common/maps"
+ "github.com/gohugoio/hugo/media"
+
+ "github.com/gohugoio/hugo/resources/images/exif"
+
+ "github.com/gohugoio/hugo/resources/resource"
+)
+
+var (
+ _ error = (*errorResource)(nil)
+ // Imnage covers all current Resource implementations.
+ _ resource.Image = (*errorResource)(nil)
+ // The list of user facing and exported interfaces in resource.go
+ // Note that if we're missing some interface here, the user will still
+ // get an error, but not as pretty.
+ _ resource.ContentResource = (*errorResource)(nil)
+ _ resource.ReadSeekCloserResource = (*errorResource)(nil)
+ _ resource.ResourcesLanguageMerger = (*resource.Resources)(nil)
+ // Make sure it also fails when passed to a pipe function.
+ _ ResourceTransformer = (*errorResource)(nil)
+)
+
+// NewErrorResource wraps err in a Resource where all but the Err method will panic.
+func NewErrorResource(err error) resource.Resource {
+ return &errorResource{error: err}
+}
+
+type errorResource struct {
+ error
+}
+
+func (e *errorResource) Err() error {
+ return e.error
+}
+
+func (e *errorResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) Content() (interface{}, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) ResourceType() string {
+ panic(e.error)
+}
+
+func (e *errorResource) MediaType() media.Type {
+ panic(e.error)
+}
+
+func (e *errorResource) Permalink() string {
+ panic(e.error)
+}
+
+func (e *errorResource) RelPermalink() string {
+ panic(e.error)
+}
+
+func (e *errorResource) Name() string {
+ panic(e.error)
+}
+
+func (e *errorResource) Title() string {
+ panic(e.error)
+}
+
+func (e *errorResource) Params() maps.Params {
+ panic(e.error)
+}
+
+func (e *errorResource) Data() interface{} {
+ panic(e.error)
+}
+
+func (e *errorResource) Height() int {
+ panic(e.error)
+}
+
+func (e *errorResource) Width() int {
+ panic(e.error)
+}
+
+func (e *errorResource) Fill(spec string) (resource.Image, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) Fit(spec string) (resource.Image, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) Resize(spec string) (resource.Image, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) Filter(filters ...interface{}) (resource.Image, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) Exif() *exif.Exif {
+ panic(e.error)
+}
+
+func (e *errorResource) DecodeImage() (image.Image, error) {
+ panic(e.error)
+}
+
+func (e *errorResource) Transform(...ResourceTransformation) (ResourceTransformer, error) {
+ panic(e.error)
+}
diff --git a/resources/page/page_nop.go b/resources/page/page_nop.go
index 94515d27d..4f91883a0 100644
--- a/resources/page/page_nop.go
+++ b/resources/page/page_nop.go
@@ -48,6 +48,10 @@ var (
// PageNop implements Page, but does nothing.
type nopPage int
+func (p *nopPage) Err() error {
+ return nil
+}
+
func (p *nopPage) Aliases() []string {
return nil
}
diff --git a/resources/page/testhelpers_test.go b/resources/page/testhelpers_test.go
index 1a0a6586a..a21ab2ff3 100644
--- a/resources/page/testhelpers_test.go
+++ b/resources/page/testhelpers_test.go
@@ -29,7 +29,6 @@ import (
"github.com/bep/gitmap"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/resources/resource"
-
"github.com/gohugoio/hugo/navigation"
@@ -121,6 +120,10 @@ type testPage struct {
sectionEntries []string
}
+func (p *testPage) Err() error {
+ return nil
+}
+
func (p *testPage) Aliases() []string {
panic("not implemented")
}
diff --git a/resources/resource.go b/resources/resource.go
index 28b9a8879..1f6246859 100644
--- a/resources/resource.go
+++ b/resources/resource.go
@@ -230,6 +230,10 @@ func (l *genericResource) Content() (interface{}, error) {
return l.content, nil
}
+func (r *genericResource) Err() error {
+ return nil
+}
+
func (l *genericResource) Data() interface{} {
return l.data
}
diff --git a/resources/resource/resourcetypes.go b/resources/resource/resourcetypes.go
index 8ab77e436..788cdb86a 100644
--- a/resources/resource/resourcetypes.go
+++ b/resources/resource/resourcetypes.go
@@ -45,6 +45,7 @@ type Resource interface {
ResourceMetaProvider
ResourceParamsProvider
ResourceDataProvider
+ Err() error
}
// Image represents an image resource.
diff --git a/resources/resource_factories/create/create.go b/resources/resource_factories/create/create.go
index dc03568ac..f7bde9ee6 100644
--- a/resources/resource_factories/create/create.go
+++ b/resources/resource_factories/create/create.go
@@ -35,7 +35,6 @@ import (
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/cache/filecache"
- "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hugio"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
@@ -155,7 +154,6 @@ func (c *Client) FromString(targetPath, content string) (resource.Resource, erro
// FromRemote expects one or n-parts of a URL to a resource
// If you provide multiple parts they will be joined together to the final URL.
func (c *Client) FromRemote(uri string, options map[string]interface{}) (resource.Resource, error) {
- defer herrors.Recover()
rURL, err := url.Parse(uri)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse URL for resource %s", uri)
diff --git a/resources/transform.go b/resources/transform.go
index 0d555b2b5..0569fb35e 100644
--- a/resources/transform.go
+++ b/resources/transform.go
@@ -167,6 +167,10 @@ func (r *resourceAdapter) Content() (interface{}, error) {
return r.target.Content()
}
+func (r *resourceAdapter) Err() error {
+ return nil
+}
+
func (r *resourceAdapter) Data() interface{} {
r.init(false, false)
return r.target.Data()
diff --git a/tpl/resources/resources.go b/tpl/resources/resources.go
index a3f3aaa3e..0be52ad05 100644
--- a/tpl/resources/resources.go
+++ b/tpl/resources/resources.go
@@ -113,30 +113,40 @@ func (ns *Namespace) getscssClientDartSass() (*dartsass.Client, error) {
// further transformations.
//
// For URLs an additional argument with options can be provided.
-func (ns *Namespace) Get(args ...interface{}) (resource.Resource, error) {
- if len(args) != 1 && len(args) != 2 {
- return nil, errors.New("must provide a filename or URL")
- }
+func (ns *Namespace) Get(args ...interface{}) resource.Resource {
+ get := func(args ...interface{}) (resource.Resource, error) {
+ if len(args) != 1 && len(args) != 2 {
+ return nil, errors.New("must provide a filename or URL")
+ }
- filenamestr, err := cast.ToStringE(args[0])
- if err != nil {
- return nil, err
- }
+ filenamestr, err := cast.ToStringE(args[0])
+ if err != nil {
+ return nil, err
+ }
- if u, err := url.Parse(filenamestr); err == nil && u.Scheme != "" {
- if len(args) == 2 {
- options, err := maps.ToStringMapE(args[1])
- if err != nil {
- return nil, err
+ if u, err := url.Parse(filenamestr); err == nil && u.Scheme != "" {
+ if len(args) == 2 {
+ options, err := maps.ToStringMapE(args[1])
+ if err != nil {
+ return nil, err
+ }
+ return ns.createClient.FromRemote(filenamestr, options)
}
- return ns.createClient.FromRemote(filenamestr, options)
+ return ns.createClient.FromRemote(filenamestr, nil)
}
- return ns.createClient.FromRemote(filenamestr, nil)
+
+ filenamestr = filepath.Clean(filenamestr)
+
+ return ns.createClient.Get(filenamestr)
}
- filenamestr = filepath.Clean(filenamestr)
+ r, err := get(args...)
+ if err != nil {
+ // This allows the client to reason about the .Err in the template.
+ return resources.NewErrorResource(errors.Wrap(err, "error calling resources.Get"))
+ }
+ return r
- return ns.createClient.Get(filenamestr)
}
// GetMatch finds the first Resource matching the given pattern, or nil if none found.