Repository: gohugoio/hugo (language: go)

Issue:
Adjust error handling in ToMath vs try
https://gohugo.io/functions/transform/tomath/#error-handling


Discussion / hints:

Fix patch:
diff --git a/common/types/types.go b/common/types/types.go
index d32391a88b7..062ecc4034f 100644
--- a/common/types/types.go
+++ b/common/types/types.go
@@ -133,22 +133,3 @@ func NewBool(b bool) *bool {
 type PrintableValueProvider interface {
 	PrintableValue() any
 }
-
-var _ PrintableValueProvider = Result[any]{}
-
-// Result is a generic result type.
-type Result[T any] struct {
-	// The result value.
-	Value T
-
-	// The error value.
-	Err error
-}
-
-// PrintableValue returns the value or panics if there is an error.
-func (r Result[T]) PrintableValue() any {
-	if r.Err != nil {
-		panic(r.Err)
-	}
-	return r.Value
-}
diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go
index 1518e2db848..7e7f61031ca 100644
--- a/hugolib/hugo_sites_build.go
+++ b/hugolib/hugo_sites_build.go
@@ -347,10 +347,14 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) 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)
+		// In Hugo 0.141.0 we replaced the special error handling for resources.GetRemote
+		// with the more general try.
+		if strings.Contains(err.Error(), "can't evaluate field Err in type") {
+			if strings.Contains(err.Error(), "resource.Resource") {
+				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)
+			} else if strings.Contains(err.Error(), "template.HTML") {
+				return fmt.Errorf("%s: the return type of transform.ToMath was changed in Hugo v0.141.0 and the error handling replaced with a new try keyword, see https://gohugo.io/functions/go-template/try/", err)
+			}
 		}
 		return err
 	}
diff --git a/tpl/transform/transform.go b/tpl/transform/transform.go
index c9af141ed7b..fc29a46df99 100644
--- a/tpl/transform/transform.go
+++ b/tpl/transform/transform.go
@@ -28,7 +28,6 @@ import (
 	"github.com/gohugoio/hugo/cache/dynacache"
 	"github.com/gohugoio/hugo/common/hashing"
 	"github.com/gohugoio/hugo/common/hugio"
-	"github.com/gohugoio/hugo/common/types"
 	"github.com/gohugoio/hugo/internal/warpc"
 	"github.com/gohugoio/hugo/markup/converter/hooks"
 	"github.com/gohugoio/hugo/markup/highlight"
@@ -200,15 +199,13 @@ func (ns *Namespace) Plainify(s any) (template.HTML, error) {
 
 // ToMath converts a LaTeX string to math in the given format, default MathML.
 // This uses KaTeX to render the math, see https://katex.org/.
-func (ns *Namespace) ToMath(ctx context.Context, args ...any) (types.Result[template.HTML], error) {
-	var res types.Result[template.HTML]
-
+func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, error) {
 	if len(args) < 1 {
-		return res, errors.New("must provide at least one argument")
+		return "", errors.New("must provide at least one argument")
 	}
 	expression, err := cast.ToStringE(args[0])
 	if err != nil {
-		return res, err
+		return "", err
 	}
 
 	katexInput := warpc.KatexInput{
@@ -223,7 +220,7 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (types.Result[temp
 
 	if len(args) > 1 {
 		if err := mapstructure.WeakDecode(args[1], &katexInput.Options); err != nil {
-			return res, err
+			return "", err
 		}
 	}
 
@@ -259,13 +256,11 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (types.Result[temp
 
 		return template.HTML(s), err
 	})
-
-	res = types.Result[template.HTML]{
-		Value: v,
-		Err:   err,
+	if err != nil {
+		return "", err
 	}
 
-	return res, nil
+	return v, nil
 }
 
 // For internal use.


Test patch:
diff --git a/tpl/transform/transform_integration_test.go b/tpl/transform/transform_integration_test.go
index 5f34ff81bf5..276b9b059f7 100644
--- a/tpl/transform/transform_integration_test.go
+++ b/tpl/transform/transform_integration_test.go
@@ -183,18 +183,38 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
 -- hugo.toml --
 disableKinds = ['page','rss','section','sitemap','taxonomy','term']
 -- layouts/index.html --
-{{ with transform.ToMath "c = \\foo{a^2 + b^2}" }}
+{{ with try (transform.ToMath "c = \\foo{a^2 + b^2}") }}
 	{{ with .Err }}
 	 	{{ warnf "error: %s" . }}
 	{{ else }}
-		{{ . }}
+		{{ .Value }}
 	{{ end }}
 {{ end }}
   `
 		b, err := hugolib.TestE(t, files, hugolib.TestOptWarn())
 
 		b.Assert(err, qt.IsNil)
-		b.AssertLogContains("WARN  error: KaTeX parse error: Undefined control sequence: \\foo")
+		b.AssertLogContains("WARN  error: template: index.html:1:22: executing \"index.html\" at <transform.ToMath>: error calling ToMath: KaTeX parse error: Undefined control sequence: \\foo at position 5: c = \\̲f̲o̲o̲{a^2 + b^2}")
+	})
+
+	// See issue 13239.
+	t.Run("Handle in template, old Err construct", func(t *testing.T) {
+		files := `
+-- hugo.toml --
+disableKinds = ['page','rss','section','sitemap','taxonomy','term']
+-- layouts/index.html --
+{{ with transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" }}
+	{{ with .Err }}
+	 	{{ warnf "error: %s" . }}
+	{{ else }}
+		{{ . }}
+	{{ end }}
+{{ end }}
+  `
+		b, err := hugolib.TestE(t, files, hugolib.TestOptWarn())
+
+		b.Assert(err, qt.IsNotNil)
+		b.Assert(err.Error(), qt.Contains, "the return type of transform.ToMath was changed in Hugo v0.141.0 and the error handling replaced with a new try keyword, see https://gohugo.io/functions/go-template/try/")
 	})
 }