mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-28 22:19:59 +02:00
resources: Replace error handling in GetRemote with try (note)
Closes #13216
This commit is contained in:
@@ -258,8 +258,27 @@ func openFile(filename string, fs afero.Fs) (afero.File, string, error) {
|
|||||||
return f, realFilename, nil
|
return f, realFilename, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cause returns the underlying error or itself if it does not implement Unwrap.
|
// Cause returns the underlying error, that is,
|
||||||
|
// it unwraps errors until it finds one that does not implement
|
||||||
|
// the Unwrap method.
|
||||||
|
// For a shallow variant, see Unwrap.
|
||||||
func Cause(err error) error {
|
func Cause(err error) error {
|
||||||
|
type unwrapper interface {
|
||||||
|
Unwrap() error
|
||||||
|
}
|
||||||
|
|
||||||
|
for err != nil {
|
||||||
|
cause, ok := err.(unwrapper)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
err = cause.Unwrap()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap returns the underlying error or itself if it does not implement Unwrap.
|
||||||
|
func Unwrap(err error) error {
|
||||||
if u := errors.Unwrap(err); u != nil {
|
if u := errors.Unwrap(err); u != nil {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
@@ -267,7 +286,7 @@ func Cause(err error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func extractFileTypePos(err error) (string, text.Position) {
|
func extractFileTypePos(err error) (string, text.Position) {
|
||||||
err = Cause(err)
|
err = Unwrap(err)
|
||||||
|
|
||||||
var fileType string
|
var fileType string
|
||||||
|
|
||||||
|
@@ -343,6 +343,18 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
|
|||||||
|
|
||||||
siteRenderContext := &siteRenderContext{cfg: config, multihost: h.Configs.IsMultihost}
|
siteRenderContext := &siteRenderContext{cfg: config, multihost: h.Configs.IsMultihost}
|
||||||
|
|
||||||
|
renderErr := func(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if strings.Contains(err.Error(), "can't evaluate field Err in type resource.Resource") {
|
||||||
|
// In Hugo 0.141.0 we replaced the special error handling for resources.GetRemote
|
||||||
|
// with the more general try.
|
||||||
|
return fmt.Errorf("%s: Resource.Err was removed in Hugo v0.141.0 and replaced with a new try keyword, see https://gohugo.io/functions/go-template/try/", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for _, s := range h.Sites {
|
for _, s := range h.Sites {
|
||||||
segmentFilter := s.conf.C.SegmentFilter
|
segmentFilter := s.conf.C.SegmentFilter
|
||||||
@@ -390,7 +402,7 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := s.render(siteRenderContext); err != nil {
|
if err := s.render(siteRenderContext); err != nil {
|
||||||
return err
|
return renderErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loggers.TimeTrackf(ll, start, nil, "")
|
loggers.TimeTrackf(ll, start, nil, "")
|
||||||
|
@@ -185,10 +185,6 @@ func (p *pageState) isContentNodeBranch() bool {
|
|||||||
return p.IsNode()
|
return p.IsNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pageState) Err() resource.ResourceError {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eq returns whether the current page equals the given page.
|
// Eq returns whether the current page equals the given page.
|
||||||
// This is what's invoked when doing `{{ if eq $page $otherPage }}`
|
// This is what's invoked when doing `{{ if eq $page $otherPage }}`
|
||||||
func (p *pageState) Eq(other any) bool {
|
func (p *pageState) Eq(other any) bool {
|
||||||
|
@@ -67,11 +67,11 @@ FIT: {{ $fit.Name }}|{{ $fit.RelPermalink }}|{{ $fit.Width }}
|
|||||||
CSS integrity Data first: {{ $cssFingerprinted1.Data.Integrity }} {{ $cssFingerprinted1.RelPermalink }}
|
CSS integrity Data first: {{ $cssFingerprinted1.Data.Integrity }} {{ $cssFingerprinted1.RelPermalink }}
|
||||||
CSS integrity Data last: {{ $cssFingerprinted2.RelPermalink }} {{ $cssFingerprinted2.Data.Integrity }}
|
CSS integrity Data last: {{ $cssFingerprinted2.RelPermalink }} {{ $cssFingerprinted2.Data.Integrity }}
|
||||||
|
|
||||||
{{ $failedImg := resources.GetRemote "%[1]s/fail.jpg" }}
|
{{ $failedImg := try (resources.GetRemote "%[1]s/fail.jpg") }}
|
||||||
{{ $rimg := resources.GetRemote "%[1]s/sunset.jpg" }}
|
{{ $rimg := resources.GetRemote "%[1]s/sunset.jpg" }}
|
||||||
{{ $remotenotfound := resources.GetRemote "%[1]s/notfound.jpg" }}
|
{{ $remotenotfound := resources.GetRemote "%[1]s/notfound.jpg" }}
|
||||||
{{ $localnotfound := resources.Get "images/notfound.jpg" }}
|
{{ $localnotfound := resources.Get "images/notfound.jpg" }}
|
||||||
{{ $gopherprotocol := resources.GetRemote "gopher://example.org" }}
|
{{ $gopherprotocol := try (resources.GetRemote "gopher://example.org") }}
|
||||||
{{ $rfit := $rimg.Fit "200x200" }}
|
{{ $rfit := $rimg.Fit "200x200" }}
|
||||||
{{ $rfit2 := $rfit.Fit "100x200" }}
|
{{ $rfit2 := $rfit.Fit "100x200" }}
|
||||||
{{ $rimg = $rimg | fingerprint }}
|
{{ $rimg = $rimg | fingerprint }}
|
||||||
@@ -79,10 +79,10 @@ SUNSET REMOTE: {{ $rimg.Name }}|{{ $rimg.RelPermalink }}|{{ $rimg.Width }}|{{ le
|
|||||||
FIT REMOTE: {{ $rfit.Name }}|{{ $rfit.RelPermalink }}|{{ $rfit.Width }}
|
FIT REMOTE: {{ $rfit.Name }}|{{ $rfit.RelPermalink }}|{{ $rfit.Width }}
|
||||||
REMOTE NOT FOUND: {{ if $remotenotfound }}FAILED{{ else}}OK{{ end }}
|
REMOTE NOT FOUND: {{ if $remotenotfound }}FAILED{{ else}}OK{{ end }}
|
||||||
LOCAL NOT FOUND: {{ if $localnotfound }}FAILED{{ else}}OK{{ end }}
|
LOCAL NOT FOUND: {{ if $localnotfound }}FAILED{{ else}}OK{{ end }}
|
||||||
PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ . | safeHTML }}{{ end }}
|
PRINT PROTOCOL ERROR1: {{ with $gopherprotocol }}{{ .Value | safeHTML }}{{ end }}
|
||||||
PRINT PROTOCOL ERROR2: {{ with $gopherprotocol }}{{ .Err | safeHTML }}{{ end }}
|
PRINT PROTOCOL ERROR2: {{ with $gopherprotocol }}{{ .Err | safeHTML }}{{ end }}
|
||||||
PRINT PROTOCOL ERROR DETAILS: {{ with $gopherprotocol }}Err: {{ .Err | safeHTML }}{{ with .Err }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}{{ end }}|{{ end }}{{ end }}
|
PRINT PROTOCOL ERROR DETAILS: {{ with $gopherprotocol }}{{ with .Err }}Err: {{ . | safeHTML }}{{ with .Cause }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}{{ end }}|{{ end }}{{ end }}{{ end }}
|
||||||
FAILED REMOTE ERROR DETAILS CONTENT: {{ with $failedImg.Err }}|{{ . }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}|ContentLength: {{ .ContentLength }}|ContentType: {{ .ContentType }}{{ end }}{{ end }}|
|
FAILED REMOTE ERROR DETAILS CONTENT: {{ with $failedImg }}{{ with .Err }}{{ with .Cause }}{{ . }}|{{ with .Data }}Body: {{ .Body }}|StatusCode: {{ .StatusCode }}|ContentLength: {{ .ContentLength }}|ContentType: {{ .ContentType }}{{ end }}{{ end }}{{ end }}{{ end }}|
|
||||||
`, ts.URL))
|
`, ts.URL))
|
||||||
|
|
||||||
fs := b.Fs.Source
|
fs := b.Fs.Source
|
||||||
@@ -114,8 +114,8 @@ SUNSET REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s.a9bf1d944e19c0f382e0d8f51de690f7d
|
|||||||
FIT REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s_hu15210517121918042184.jpg|200
|
FIT REMOTE: /sunset_%[1]s.jpg|/sunset_%[1]s_hu15210517121918042184.jpg|200
|
||||||
REMOTE NOT FOUND: OK
|
REMOTE NOT FOUND: OK
|
||||||
LOCAL NOT FOUND: OK
|
LOCAL NOT FOUND: OK
|
||||||
PRINT PROTOCOL ERROR DETAILS: Err: error calling resources.GetRemote: Get "gopher://example.org": unsupported protocol scheme "gopher"||
|
PRINT PROTOCOL ERROR DETAILS: Err: template: index.html:22:36: executing "index.html" at <resources.GetRemote>: error calling GetRemote: Get "gopher://example.org": unsupported protocol scheme "gopher"|
|
||||||
FAILED REMOTE ERROR DETAILS CONTENT: |failed to fetch remote resource from '%[2]s/fail.jpg': Not Implemented|Body: { msg: failed }
|
FAILED REMOTE ERROR DETAILS CONTENT: failed to fetch remote resource from '%[2]s/fail.jpg': Not Implemented|Body: { msg: failed }
|
||||||
|StatusCode: 501|ContentLength: 16|ContentType: text/plain; charset=utf-8|
|
|StatusCode: 501|ContentLength: 16|ContentType: text/plain; charset=utf-8|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,145 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"context"
|
|
||||||
"image"
|
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
|
||||||
"github.com/gohugoio/hugo/common/maps"
|
|
||||||
"github.com/gohugoio/hugo/media"
|
|
||||||
"github.com/gohugoio/hugo/resources/images"
|
|
||||||
"github.com/gohugoio/hugo/resources/images/exif"
|
|
||||||
"github.com/gohugoio/hugo/resources/resource"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ error = (*errorResource)(nil)
|
|
||||||
// Image covers all current Resource implementations.
|
|
||||||
_ images.ImageResource = (*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 resource.ResourceError) resource.Resource {
|
|
||||||
return &errorResource{ResourceError: err}
|
|
||||||
}
|
|
||||||
|
|
||||||
type errorResource struct {
|
|
||||||
resource.ResourceError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Err() resource.ResourceError {
|
|
||||||
return e.ResourceError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Content(context.Context) (any, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) ResourceType() string {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) MediaType() media.Type {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Permalink() string {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) RelPermalink() string {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Name() string {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Title() string {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Params() maps.Params {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Data() any {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Height() int {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Width() int {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Process(spec string) (images.ImageResource, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Crop(spec string) (images.ImageResource, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Fill(spec string) (images.ImageResource, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Fit(spec string) (images.ImageResource, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Resize(spec string) (images.ImageResource, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Filter(filters ...any) (images.ImageResource, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Exif() *exif.ExifInfo {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Colors() ([]images.Color, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) DecodeImage() (image.Image, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) Transform(...ResourceTransformation) (ResourceTransformer, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errorResource) TransformWithContext(context.Context, ...ResourceTransformation) (ResourceTransformer, error) {
|
|
||||||
panic(e.ResourceError)
|
|
||||||
}
|
|
@@ -61,10 +61,6 @@ type nopPage int
|
|||||||
|
|
||||||
var noOpPathInfo = media.DefaultPathParser.Parse(files.ComponentFolderContent, "no-op.md")
|
var noOpPathInfo = media.DefaultPathParser.Parse(files.ComponentFolderContent, "no-op.md")
|
||||||
|
|
||||||
func (p *nopPage) Err() resource.ResourceError {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *nopPage) Aliases() []string {
|
func (p *nopPage) Aliases() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -111,10 +111,6 @@ type testPage struct {
|
|||||||
sectionEntries []string
|
sectionEntries []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Err() resource.ResourceError {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *testPage) Aliases() []string {
|
func (p *testPage) Aliases() []string {
|
||||||
panic("testpage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
@@ -224,9 +224,6 @@ type resourceCopier interface {
|
|||||||
|
|
||||||
// Copy copies r to the targetPath given.
|
// Copy copies r to the targetPath given.
|
||||||
func Copy(r resource.Resource, targetPath string) resource.Resource {
|
func Copy(r resource.Resource, targetPath string) resource.Resource {
|
||||||
if r.Err() != nil {
|
|
||||||
panic(fmt.Sprintf("Resource has an .Err: %s", r.Err()))
|
|
||||||
}
|
|
||||||
return r.(resourceCopier).cloneTo(targetPath)
|
return r.(resourceCopier).cloneTo(targetPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,10 +436,6 @@ func (l *genericResource) Content(context.Context) (any, error) {
|
|||||||
return hugio.ReadString(r)
|
return hugio.ReadString(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *genericResource) Err() resource.ResourceError {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *genericResource) Data() any {
|
func (l *genericResource) Data() any {
|
||||||
return l.sd.Data
|
return l.sd.Data
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,9 @@ type OriginProvider interface {
|
|||||||
|
|
||||||
// NewResourceError creates a new ResourceError.
|
// NewResourceError creates a new ResourceError.
|
||||||
func NewResourceError(err error, data any) ResourceError {
|
func NewResourceError(err error, data any) ResourceError {
|
||||||
|
if data == nil {
|
||||||
|
data = map[string]any{}
|
||||||
|
}
|
||||||
return &resourceError{
|
return &resourceError{
|
||||||
error: err,
|
error: err,
|
||||||
data: data,
|
data: data,
|
||||||
@@ -65,13 +68,6 @@ type ResourceError interface {
|
|||||||
ResourceDataProvider
|
ResourceDataProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrProvider provides an Err.
|
|
||||||
type ErrProvider interface {
|
|
||||||
// Err returns an error if this resource is in an error state.
|
|
||||||
// This will currently only be set for resources obtained from resources.GetRemote.
|
|
||||||
Err() ResourceError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource represents a linkable resource, i.e. a content page, image etc.
|
// Resource represents a linkable resource, i.e. a content page, image etc.
|
||||||
type Resource interface {
|
type Resource interface {
|
||||||
ResourceWithoutMeta
|
ResourceWithoutMeta
|
||||||
@@ -83,7 +79,6 @@ type ResourceWithoutMeta interface {
|
|||||||
MediaTypeProvider
|
MediaTypeProvider
|
||||||
ResourceLinksProvider
|
ResourceLinksProvider
|
||||||
ResourceDataProvider
|
ResourceDataProvider
|
||||||
ErrProvider
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceWrapper interface {
|
type ResourceWrapper interface {
|
||||||
|
@@ -31,18 +31,17 @@ func TestGetRemoteHead(t *testing.T) {
|
|||||||
[security.http]
|
[security.http]
|
||||||
methods = ['(?i)GET|POST|HEAD']
|
methods = ['(?i)GET|POST|HEAD']
|
||||||
urls = ['.*gohugo\.io.*']
|
urls = ['.*gohugo\.io.*']
|
||||||
|
|
||||||
-- layouts/index.html --
|
-- layouts/index.html --
|
||||||
{{ $url := "https://gohugo.io/img/hugo.png" }}
|
{{ $url := "https://gohugo.io/img/hugo.png" }}
|
||||||
{{ $opts := dict "method" "head" }}
|
{{ $opts := dict "method" "head" }}
|
||||||
{{ with resources.GetRemote $url $opts }}
|
{{ with try (resources.GetRemote $url $opts) }}
|
||||||
{{ with .Err }}
|
{{ with .Err }}
|
||||||
{{ errorf "Unable to get remote resource: %s" . }}
|
{{ errorf "Unable to get remote resource: %s" . }}
|
||||||
{{ else }}
|
{{ else with .Value }}
|
||||||
Head Content: {{ .Content }}. Head Data: {{ .Data }}
|
Head Content: {{ .Content }}. Head Data: {{ .Data }}
|
||||||
{{ end }}
|
{{ else }}
|
||||||
{{ else }}
|
|
||||||
{{ errorf "Unable to get remote resource: %s" $url }}
|
{{ errorf "Unable to get remote resource: %s" $url }}
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -90,14 +89,15 @@ mediaTypes = ['text/plain']
|
|||||||
-- layouts/_default/single.html --
|
-- layouts/_default/single.html --
|
||||||
{{ $url := printf "%s%s" "URL" .RelPermalink}}
|
{{ $url := printf "%s%s" "URL" .RelPermalink}}
|
||||||
{{ $opts := dict }}
|
{{ $opts := dict }}
|
||||||
{{ with resources.GetRemote $url $opts }}
|
{{ with try (resources.GetRemote $url $opts) }}
|
||||||
{{ with .Err }}
|
{{ with .Err }}
|
||||||
{{ errorf "Got Err: %s. Data: %v" . .Data }}
|
{{ errorf "Got Err: %s" . }}
|
||||||
{{ else }}
|
{{ with .Cause }}{{ errorf "Data: %s" .Data }}{{ end }}
|
||||||
|
{{ else with .Value }}
|
||||||
Content: {{ .Content }}
|
Content: {{ .Content }}
|
||||||
|
{{ else }}
|
||||||
|
{{ errorf "Unable to get remote resource: %s" $url }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ else }}
|
|
||||||
{{ errorf "Unable to get remote resource: %s" $url }}
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@@ -192,10 +192,6 @@ func (r *resourceAdapter) Content(ctx context.Context) (any, error) {
|
|||||||
return r.target.Content(ctx)
|
return r.target.Content(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *resourceAdapter) Err() resource.ResourceError {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *resourceAdapter) GetIdentity() identity.Identity {
|
func (r *resourceAdapter) GetIdentity() identity.Identity {
|
||||||
return identity.FirstIdentity(r.target)
|
return identity.FirstIdentity(r.target)
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/common/herrors"
|
||||||
"github.com/gohugoio/hugo/common/hreflect"
|
"github.com/gohugoio/hugo/common/hreflect"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"
|
"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"
|
||||||
@@ -256,14 +257,34 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
|
|||||||
panic("not reached")
|
panic("not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newErrorWithCause creates a new error with the given cause.
|
||||||
|
func newErrorWithCause(err error) *TryError {
|
||||||
|
return &TryError{Err: err, Cause: herrors.Cause(err)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryError wraps an error with a cause.
|
||||||
|
type TryError struct {
|
||||||
|
Err error
|
||||||
|
Cause error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TryError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TryError) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
// TryValue is what gets returned when using the "try" keyword.
|
// TryValue is what gets returned when using the "try" keyword.
|
||||||
type TryValue struct {
|
type TryValue struct {
|
||||||
// Value is the value returned by the function or method wrapped with "try".
|
// Value is the value returned by the function or method wrapped with "try".
|
||||||
// This will always be nil if Err is set.
|
// This will always be nil if Err is set.
|
||||||
Value any
|
Value any
|
||||||
|
|
||||||
// Err is the error returned by the function or method wrapped with "try".
|
// Err is the error returned by the function or method wrapped with "try".
|
||||||
// This will always be nil if Value is set.
|
// This will always be nil if Value is set.
|
||||||
Err error
|
Err *TryError
|
||||||
}
|
}
|
||||||
|
|
||||||
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
|
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
|
||||||
@@ -274,10 +295,11 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
|
|||||||
if name == "try" {
|
if name == "try" {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
// Cause: herrors.Cause(err)
|
||||||
if err, ok := r.(error); ok {
|
if err, ok := r.(error); ok {
|
||||||
val = reflect.ValueOf(TryValue{nil, err})
|
val = reflect.ValueOf(TryValue{Value: nil, Err: newErrorWithCause(err)})
|
||||||
} else {
|
} else {
|
||||||
val = reflect.ValueOf(TryValue{nil, fmt.Errorf("%v", r)})
|
val = reflect.ValueOf(TryValue{Value: nil, Err: newErrorWithCause(fmt.Errorf("%v", r))})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -396,7 +418,7 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
|
|||||||
|
|
||||||
// Added for Hugo.
|
// Added for Hugo.
|
||||||
if name == "try" {
|
if name == "try" {
|
||||||
return reflect.ValueOf(TryValue{vv.Interface(), nil})
|
return reflect.ValueOf(TryValue{Value: vv.Interface()})
|
||||||
}
|
}
|
||||||
|
|
||||||
return vv
|
return vv
|
||||||
|
@@ -115,14 +115,10 @@ func (ns *Namespace) Get(filename any) resource.Resource {
|
|||||||
//
|
//
|
||||||
// Note: This method does not return any error as a second return value,
|
// Note: This method does not return any error as a second return value,
|
||||||
// for any error situations the error can be checked in .Err.
|
// for any error situations the error can be checked in .Err.
|
||||||
func (ns *Namespace) GetRemote(args ...any) resource.Resource {
|
func (ns *Namespace) GetRemote(args ...any) (resource.Resource, error) {
|
||||||
get := func(args ...any) (resource.Resource, error) {
|
get := func(args ...any) (resource.Resource, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 || len(args) > 2 {
|
||||||
return nil, errors.New("must provide an URL")
|
return nil, errors.New("must provide an URL and optionally an options map")
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) > 2 {
|
|
||||||
return nil, errors.New("must not provide more arguments than URL and options")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
urlstr, err := cast.ToStringE(args[0])
|
urlstr, err := cast.ToStringE(args[0])
|
||||||
@@ -146,12 +142,12 @@ func (ns *Namespace) GetRemote(args ...any) resource.Resource {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
switch v := err.(type) {
|
switch v := err.(type) {
|
||||||
case *create.HTTPError:
|
case *create.HTTPError:
|
||||||
return resources.NewErrorResource(resource.NewResourceError(v, v.Data))
|
return nil, resource.NewResourceError(v, v.Data)
|
||||||
default:
|
default:
|
||||||
return resources.NewErrorResource(resource.NewResourceError(fmt.Errorf("error calling resources.GetRemote: %w", err), make(map[string]any)))
|
return nil, resource.NewResourceError(err, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMatch finds the first Resource matching the given pattern, or nil if none found.
|
// GetMatch finds the first Resource matching the given pattern, or nil if none found.
|
||||||
|
@@ -17,13 +17,13 @@
|
|||||||
{{- $url := printf "https://twitter.com/%v/status/%v" .user .id -}}
|
{{- $url := printf "https://twitter.com/%v/status/%v" .user .id -}}
|
||||||
{{- $query := querify "url" $url "dnt" .dnt -}}
|
{{- $query := querify "url" $url "dnt" .dnt -}}
|
||||||
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
|
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
|
||||||
{{- with resources.GetRemote $request -}}
|
{{- with try (resources.GetRemote $request) -}}
|
||||||
{{- with .Err -}}
|
{{- with .Err -}}
|
||||||
{{- errorf "%s" . -}}
|
{{- errorf "%s" . -}}
|
||||||
{{- else -}}
|
{{- else with .Value -}}
|
||||||
{{- (. | transform.Unmarshal).html | safeHTML -}}
|
{{- (. | transform.Unmarshal).html | safeHTML -}}
|
||||||
{{- end -}}
|
{{- else -}}
|
||||||
{{- else -}}
|
|
||||||
{{- warnidf "shortcode-twitter-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
|
{{- warnidf "shortcode-twitter-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
|
||||||
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
@@ -14,14 +14,14 @@
|
|||||||
{{- $url := printf "https://twitter.com/%v/status/%v" .user .id -}}
|
{{- $url := printf "https://twitter.com/%v/status/%v" .user .id -}}
|
||||||
{{- $query := querify "url" $url "dnt" .dnt "omit_script" true -}}
|
{{- $query := querify "url" $url "dnt" .dnt "omit_script" true -}}
|
||||||
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
|
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
|
||||||
{{- with resources.GetRemote $request -}}
|
{{- with try (resources.GetRemote $request) -}}
|
||||||
{{- with .Err -}}
|
{{- with .Err -}}
|
||||||
{{- errorf "%s" . -}}
|
{{- errorf "%s" . -}}
|
||||||
{{- else -}}
|
{{- else with .Value -}}
|
||||||
{{- (. | transform.Unmarshal).html | safeHTML -}}
|
{{- (. | transform.Unmarshal).html | safeHTML -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- warnidf "shortcode-twitter-simple-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- else -}}
|
|
||||||
{{- warnidf "shortcode-twitter-simple-getremote" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
@@ -31,7 +31,16 @@
|
|||||||
{{- .Page.Scratch.Set "__h_simple_twitter_css" true -}}
|
{{- .Page.Scratch.Set "__h_simple_twitter_css" true -}}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.twitter-tweet {
|
.twitter-tweet {
|
||||||
font: 14px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
|
font:
|
||||||
|
14px/1.45 -apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
"Segoe UI",
|
||||||
|
Roboto,
|
||||||
|
Oxygen-Sans,
|
||||||
|
Ubuntu,
|
||||||
|
Cantarell,
|
||||||
|
"Helvetica Neue",
|
||||||
|
sans-serif;
|
||||||
border-left: 4px solid #2b7bb9;
|
border-left: 4px solid #2b7bb9;
|
||||||
padding-left: 1.5em;
|
padding-left: 1.5em;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
@@ -23,10 +23,10 @@
|
|||||||
{{- $url := urls.JoinPath "https://vimeo.com" .id -}}
|
{{- $url := urls.JoinPath "https://vimeo.com" .id -}}
|
||||||
{{- $query := querify "url" $url "dnt" $dnt -}}
|
{{- $query := querify "url" $url "dnt" $dnt -}}
|
||||||
{{- $request := printf "https://vimeo.com/api/oembed.json?%s" $query -}}
|
{{- $request := printf "https://vimeo.com/api/oembed.json?%s" $query -}}
|
||||||
{{- with resources.GetRemote $request -}}
|
{{- with try (resources.GetRemote $request) -}}
|
||||||
{{- with .Err -}}
|
{{- with .Err -}}
|
||||||
{{- errorf "%s" . -}}
|
{{- errorf "%s" . -}}
|
||||||
{{- else -}}
|
{{- else with .Value -}}
|
||||||
{{- with . | transform.Unmarshal -}}
|
{{- with . | transform.Unmarshal -}}
|
||||||
{{- $class := printf "%s %s" "s_video_simple" "__h_video" -}}
|
{{- $class := printf "%s %s" "s_video_simple" "__h_video" -}}
|
||||||
{{- with $.class -}}
|
{{- with $.class -}}
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- warnidf "shortcode-vimeo-simple" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- else -}}
|
|
||||||
{{- warnidf "shortcode-vimeo-simple" "The %q shortcode was unable to retrieve the remote data. See %s" .name .position -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
Reference in New Issue
Block a user