Repository: gohugoio/hugo (language: go)

Issue:
Create math.Abs template function
https://pkg.go.dev/math#Abs


Discussion / hints:

Fix patch:
diff --git a/docs/content/en/functions/math.md b/docs/content/en/functions/math.md
index 4abf34d1d51..e0222f3b29c 100644
--- a/docs/content/en/functions/math.md
+++ b/docs/content/en/functions/math.md
@@ -3,7 +3,7 @@ title: Math
 description: Hugo provides mathematical operators in templates.
 date: 2017-02-01
 publishdate: 2017-02-01
-lastmod: 2023-03-11
+lastmod: 2023-05-15
 keywords: [math, operators]
 categories: [functions]
 menu:
@@ -31,6 +31,7 @@ aliases: []
 |              | *If one of the numbers is a float, the result is a float.*                  | `{{ div 6 4.0 }}` &rarr; `1.5`      |
 | `mod`        | Modulus of two integers.                                                    | `{{ mod 15 3 }}` &rarr; `0`         |
 | `modBool`    | Boolean of modulus of two integers. Evaluates to `true` if result equals 0. | `{{ modBool 15 3 }}` &rarr; `true`  |
+| `math.Abs`   | Returns the absolute value of the given number.                             | `{{ math.Abs -2.1 }}` &rarr; `2.1`  |
 | `math.Ceil`  | Returns the least integer value greater than or equal to the given number.  | `{{ math.Ceil 2.1 }}` &rarr; `3`    |
 | `math.Floor` | Returns the greatest integer value less than or equal to the given number.  | `{{ math.Floor 1.9 }}` &rarr; `1`   |
 | `math.Log`   | Returns the natural logarithm of the given number.                          | `{{ math.Log 42 }}` &rarr; `3.737`  |
diff --git a/tpl/math/init.go b/tpl/math/init.go
index 67aa95f4164..8596ff64705 100644
--- a/tpl/math/init.go
+++ b/tpl/math/init.go
@@ -31,6 +31,13 @@ func init() {
 			Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
 		}
 
+		ns.AddMethodMapping(ctx.Abs,
+			nil,
+			[][2]string{
+				{"{{ math.Abs -2.1 }}", "2.1"},
+			},
+		)
+
 		ns.AddMethodMapping(ctx.Add,
 			[]string{"add"},
 			[][2]string{
diff --git a/tpl/math/math.go b/tpl/math/math.go
index a1c12425f49..374f80f8d21 100644
--- a/tpl/math/math.go
+++ b/tpl/math/math.go
@@ -35,6 +35,16 @@ func New() *Namespace {
 // Namespace provides template functions for the "math" namespace.
 type Namespace struct{}
 
+// Abs returns the absolute value of n.
+func (ns *Namespace) Abs(n any) (float64, error) {
+	af, err := cast.ToFloat64E(n)
+	if err != nil {
+		return 0, errors.New("the math.Abs function requires a numeric argument")
+	}
+
+	return math.Abs(af), nil
+}
+
 // Add adds the multivalued addends n1 and n2 or more values.
 func (ns *Namespace) Add(inputs ...any) (any, error) {
 	return ns.doArithmetic(inputs, '+')


Test patch:
diff --git a/tpl/math/math_test.go b/tpl/math/math_test.go
index 3e83405fd60..fad86938df0 100644
--- a/tpl/math/math_test.go
+++ b/tpl/math/math_test.go
@@ -63,6 +63,33 @@ func TestBasicNSArithmetic(t *testing.T) {
 	}
 }
 
+func TestAbs(t *testing.T) {
+	t.Parallel()
+	c := qt.New(t)
+	ns := New()
+
+	for _, test := range []struct {
+		x      any
+		expect any
+	}{
+		{0.0, 0.0},
+		{1.5, 1.5},
+		{-1.5, 1.5},
+		{-2, 2.0},
+		{"abc", false},
+	} {
+		result, err := ns.Abs(test.x)
+
+		if b, ok := test.expect.(bool); ok && !b {
+			c.Assert(err, qt.Not(qt.IsNil))
+			continue
+		}
+
+		c.Assert(err, qt.IsNil)
+		c.Assert(result, qt.Equals, test.expect)
+	}
+}
+
 func TestCeil(t *testing.T) {
 	t.Parallel()
 	c := qt.New(t)