mirror of
https://github.com/gohugoio/hugo.git
synced 2025-09-02 22:52:51 +02:00
Truncated; .Site.Params; First function
* Add `.Truncated` bool to each page; will be set true if the `.Summary` is truncated and it's worth showing a "more" link of some kind. * Add `Params` to the site config, defining `.Site.Params` accessible to each page; this lets the site maintainer associate arbitrary data with names, on a site-wide basis. * Provide a `First` function to templates: * Use-case: `{{range First 5 .Site.Recent}}` or anything else which is a simple iterable provided by hugolib * Tests by me for `.Truncated` and `First` Also @noahcampbell contributed towards this: * Add UnitTest for `.Site.Params`: > Digging into this test case a bit more, I'm realizing that we need > to create a param test case to ensure that for each type we render > (page, index, homepage, rss, etc.) that the proper fields are > represented. This will help us refactor without fear in the > future. Sample config.yaml: ```yaml title: "Test site" params: Subtitle: "More tests always good" AuthorName: "John Doe" SidebarRecentLimit: 5 ``` Signed-off-by: Noah Campbell <noahcampbell@gmail.com>
This commit is contained in:
committed by
Noah Campbell
parent
6017599a3c
commit
40d05f12a7
@@ -1,6 +1,7 @@
|
||||
package bundle
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/eknkc/amber"
|
||||
helpers "github.com/spf13/hugo/template"
|
||||
"html/template"
|
||||
@@ -40,6 +41,36 @@ func Gt(a interface{}, b interface{}) bool {
|
||||
return left > right
|
||||
}
|
||||
|
||||
// First is exposed to templates, to iterate over the first N items in a
|
||||
// rangeable list.
|
||||
func First(limit int, seq interface{}) (interface{}, error) {
|
||||
if limit < 1 {
|
||||
return nil, errors.New("can't return negative/empty count of items from sequence")
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
// this is better than my first pass; ripped from text/template/exec.go indirect():
|
||||
for ; seqv.Kind() == reflect.Ptr || seqv.Kind() == reflect.Interface; seqv = seqv.Elem() {
|
||||
if seqv.IsNil() {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
}
|
||||
if seqv.Kind() == reflect.Interface && seqv.NumMethod() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
switch seqv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
// okay
|
||||
default:
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
|
||||
}
|
||||
if limit > seqv.Len() {
|
||||
limit = seqv.Len()
|
||||
}
|
||||
return seqv.Slice(0, limit).Interface(), nil
|
||||
}
|
||||
|
||||
func IsSet(a interface{}, key interface{}) bool {
|
||||
av := reflect.ValueOf(a)
|
||||
kv := reflect.ValueOf(key)
|
||||
@@ -113,6 +144,7 @@ func NewTemplate() Template {
|
||||
"isset": IsSet,
|
||||
"echoParam": ReturnWhenSet,
|
||||
"safeHtml": SafeHtml,
|
||||
"First": First,
|
||||
}
|
||||
|
||||
templates.Funcs(funcMap)
|
||||
|
55
template/bundle/template_test.go
Normal file
55
template/bundle/template_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package bundle
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGt(t *testing.T) {
|
||||
for i, this := range []struct{
|
||||
left interface{}
|
||||
right interface{}
|
||||
leftShouldWin bool
|
||||
}{
|
||||
{ 5, 8, false },
|
||||
{ 8, 5, true },
|
||||
{ 5, 5, false },
|
||||
{ -2, 1, false },
|
||||
{ 2, -5, true },
|
||||
{ "8", "5", true },
|
||||
{ "5", "0001", true },
|
||||
{ []int{100,99}, []int{1,2,3,4}, false },
|
||||
} {
|
||||
leftIsBigger := Gt(this.left, this.right)
|
||||
if leftIsBigger != this.leftShouldWin {
|
||||
var which string
|
||||
if leftIsBigger {
|
||||
which = "expected right to be bigger, but left was"
|
||||
} else {
|
||||
which = "expected left to be bigger, but right was"
|
||||
}
|
||||
t.Errorf("[%d] %v compared to %v: %s", i, this.left, this.right, which)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirst(t *testing.T) {
|
||||
for i, this := range []struct{
|
||||
count int
|
||||
sequence interface{}
|
||||
expect interface{}
|
||||
} {
|
||||
{ 2, []string{"a", "b", "c"}, []string{"a", "b"} },
|
||||
{ 3, []string{"a", "b"}, []string{"a", "b"} },
|
||||
{ 2, []int{100, 200, 300}, []int{100, 200} },
|
||||
} {
|
||||
results, err := First(this.count, this.sequence)
|
||||
if err != nil {
|
||||
t.Errorf("[%d] failed: %s", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(results, this.expect) {
|
||||
t.Errorf("[%d] First %d items, got %v but expected %v", i, this.count, results, this.expect)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user