shithub: hugo

Download patch

ref: 34c566773a1364077e1397daece85b22948dc721
parent: 41805dca9e40e9b0952e04d06074e6fc91140495
author: Artem Sidorenko <[email protected]>
date: Sun Jul 2 20:20:49 EDT 2017

tpl/math: Add log function

It might be very useful for building tag clouds.

--- a/docs/content/templates/functions.md
+++ b/docs/content/templates/functions.md
@@ -433,6 +433,12 @@
 </tr>
 
 <tr>
+<td><code>math.Log</code></td>
+<td>Natural logarithm of one float.</td>
+<td><code>{{math.Log 1.0}}</code> → 0</td>
+</tr>
+
+<tr>
 <td><code>mod</code></td>
 <td>Modulus of two integers.</td>
 <td><code>{{mod 15 3}}</code> → 0</td>
@@ -714,7 +720,7 @@
 
 * `{{ "this is a text" | truncate 10 " ..." }}` → `this is a ...`
 * `{{ "<em>Keep my HTML</em>" | safeHTML | truncate 10 }}` → `<em>Keep my …</em>`
-* `{{ "With [Markdown](#markdown) inside." | markdownify | truncate 10 }}` → `With <a href='#markdown'>Markdown …</a>`  
+* `{{ "With [Markdown](#markdown) inside." | markdownify | truncate 10 }}` → `With <a href='#markdown'>Markdown …</a>`
 
 ### split
 
--- a/tpl/math/init.go
+++ b/tpl/math/init.go
@@ -43,6 +43,13 @@
 			},
 		)
 
+		ns.AddMethodMapping(ctx.Log,
+			nil,
+			[][2]string{
+				{"{{math.Log 1}}", "0"},
+			},
+		)
+
 		ns.AddMethodMapping(ctx.Mod,
 			[]string{"mod"},
 			[][2]string{
--- a/tpl/math/math.go
+++ b/tpl/math/math.go
@@ -15,7 +15,10 @@
 
 import (
 	"errors"
+	"math"
 	"reflect"
+
+	"github.com/spf13/cast"
 )
 
 // New returns a new instance of the math-namespaced template functions.
@@ -32,6 +35,16 @@
 
 func (ns *Namespace) Div(a, b interface{}) (interface{}, error) {
 	return DoArithmetic(a, b, '/')
+}
+
+func (ns *Namespace) Log(a interface{}) (float64, error) {
+	af, err := cast.ToFloat64E(a)
+
+	if err != nil {
+		return 0, errors.New("Log operator can't be used with non integer or float value")
+	}
+
+	return math.Log(af), nil
 }
 
 // Mod returns a % b.
--- a/tpl/math/math_test.go
+++ b/tpl/math/math_test.go
@@ -15,6 +15,7 @@
 
 import (
 	"fmt"
+	"math"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -135,6 +136,42 @@
 		if b, ok := test.expect.(bool); ok && !b {
 			require.Error(t, err, errMsg)
 			continue
+		}
+
+		require.NoError(t, err, errMsg)
+		assert.Equal(t, test.expect, result, errMsg)
+	}
+}
+
+func TestLog(t *testing.T) {
+	t.Parallel()
+
+	ns := New()
+
+	for i, test := range []struct {
+		a      interface{}
+		expect interface{}
+	}{
+		{1, float64(0)},
+		{3, float64(1.0986)},
+		{0, float64(math.Inf(-1))},
+		{1.0, float64(0)},
+		{3.1, float64(1.1314)},
+		{"abc", false},
+	} {
+		errMsg := fmt.Sprintf("[%d] %v", i, test)
+
+		result, err := ns.Log(test.a)
+
+		if b, ok := test.expect.(bool); ok && !b {
+			require.Error(t, err, errMsg)
+			continue
+		}
+
+		// we compare only 4 digits behind point if its a real float
+		// otherwise we usually get different float values on the last positions
+		if result != math.Inf(-1) {
+			result = float64(int(result*10000)) / 10000
 		}
 
 		require.NoError(t, err, errMsg)