tpl: split template.go - hugo - [fork] hugo port for 9front
 (HTM) git clone git@git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit be2097e1ad789eca5d893805a059d94defbe5c48
 (DIR) parent 42dcaabf4f81ccd8aa831049440bb0c5d85707d6
 (HTM) Author: bep <bjorn.erik.pedersen@gmail.com>
       Date:   Sun,  5 Apr 2015 21:03:16 +0200
       
       tpl: split template.go
       
       The template funcs get their own file. This prevents having to scroll miles to get to the template infrastructure.
       
       Diffstat:
         M tpl/template.go                     |    1206 -------------------------------
         A tpl/template_funcs.go               |    1228 +++++++++++++++++++++++++++++++
         C tpl/template_test.go -> tpl/templa… |       0 
         M tpl/template_test.go                |    1221 +------------------------------
       
       4 files changed, 1229 insertions(+), 2426 deletions(-)
       ---
 (DIR) diff --git a/tpl/template.go b/tpl/template.go
       @@ -15,30 +15,22 @@ package tpl
        
        import (
                "bytes"
       -        "errors"
       -        "fmt"
                "github.com/eknkc/amber"
       -        "github.com/spf13/cast"
                bp "github.com/spf13/hugo/bufferpool"
                "github.com/spf13/hugo/helpers"
                "github.com/spf13/hugo/hugofs"
                jww "github.com/spf13/jwalterweatherman"
                "github.com/yosssi/ace"
       -        "html"
                "html/template"
                "io"
                "io/ioutil"
                "os"
                "path/filepath"
       -        "reflect"
       -        "sort"
       -        "strconv"
                "strings"
        )
        
        var localTemplates *template.Template
        var tmpl Template
       -var funcMap template.FuncMap
        
        type Template interface {
                ExecuteTemplate(wr io.Writer, name string, data interface{}) error
       @@ -93,1123 +85,6 @@ func New() Template {
                return templates
        }
        
       -func Eq(x, y interface{}) bool {
       -        normalize := func(v interface{}) interface{} {
       -                vv := reflect.ValueOf(v)
       -                switch vv.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        return vv.Int()
       -                case reflect.Float32, reflect.Float64:
       -                        return vv.Float()
       -                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       -                        return vv.Uint()
       -                default:
       -                        return v
       -                }
       -        }
       -        x = normalize(x)
       -        y = normalize(y)
       -        return reflect.DeepEqual(x, y)
       -}
       -
       -func Ne(x, y interface{}) bool {
       -        return !Eq(x, y)
       -}
       -
       -func Ge(a, b interface{}) bool {
       -        left, right := compareGetFloat(a, b)
       -        return left >= right
       -}
       -
       -func Gt(a, b interface{}) bool {
       -        left, right := compareGetFloat(a, b)
       -        return left > right
       -}
       -
       -func Le(a, b interface{}) bool {
       -        left, right := compareGetFloat(a, b)
       -        return left <= right
       -}
       -
       -func Lt(a, b interface{}) bool {
       -        left, right := compareGetFloat(a, b)
       -        return left < right
       -}
       -
       -func compareGetFloat(a interface{}, b interface{}) (float64, float64) {
       -        var left, right float64
       -        var leftStr, rightStr *string
       -        var err error
       -        av := reflect.ValueOf(a)
       -
       -        switch av.Kind() {
       -        case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
       -                left = float64(av.Len())
       -        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                left = float64(av.Int())
       -        case reflect.Float32, reflect.Float64:
       -                left = av.Float()
       -        case reflect.String:
       -                left, err = strconv.ParseFloat(av.String(), 64)
       -                if err != nil {
       -                        str := av.String()
       -                        leftStr = &str
       -                }
       -        }
       -
       -        bv := reflect.ValueOf(b)
       -
       -        switch bv.Kind() {
       -        case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
       -                right = float64(bv.Len())
       -        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                right = float64(bv.Int())
       -        case reflect.Float32, reflect.Float64:
       -                right = bv.Float()
       -        case reflect.String:
       -                right, err = strconv.ParseFloat(bv.String(), 64)
       -                if err != nil {
       -                        str := bv.String()
       -                        rightStr = &str
       -                }
       -
       -        }
       -
       -        switch {
       -        case leftStr == nil || rightStr == nil:
       -        case *leftStr < *rightStr:
       -                return 0, 1
       -        case *leftStr > *rightStr:
       -                return 1, 0
       -        default:
       -                return 0, 0
       -        }
       -
       -        return left, right
       -}
       -
       -// Slicing in Slicestr is done by specifying a half-open range with
       -// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
       -// The end index can be omitted, it defaults to the string's length.
       -func Slicestr(a interface{}, startEnd ...int) (string, error) {
       -        aStr, err := cast.ToStringE(a)
       -        if err != nil {
       -                return "", err
       -        }
       -
       -        if len(startEnd) > 2 {
       -                return "", errors.New("too many arguments")
       -        }
       -
       -        if len(startEnd) == 2 {
       -                return aStr[startEnd[0]:startEnd[1]], nil
       -        } else if len(startEnd) == 1 {
       -                return aStr[startEnd[0]:], nil
       -        } else {
       -                return aStr[:], nil
       -        }
       -
       -}
       -
       -// Substr extracts parts of a string, beginning at the character at the specified
       -// position, and returns the specified number of characters.
       -//
       -// It normally takes two parameters: start and length.
       -// It can also take one parameter: start, i.e. length is omitted, in which case
       -// the substring starting from start until the end of the string will be returned.
       -//
       -// To extract characters from the end of the string, use a negative start number.
       -//
       -// In addition, borrowing from the extended behavior described at http://php.net/substr,
       -// if length is given and is negative, then that many characters will be omitted from
       -// the end of string.
       -func Substr(a interface{}, nums ...int) (string, error) {
       -        aStr, err := cast.ToStringE(a)
       -        if err != nil {
       -                return "", err
       -        }
       -
       -        var start, length int
       -        switch len(nums) {
       -        case 1:
       -                start = nums[0]
       -                length = len(aStr)
       -        case 2:
       -                start = nums[0]
       -                length = nums[1]
       -        default:
       -                return "", errors.New("too many arguments")
       -        }
       -
       -        if start < -len(aStr) {
       -                start = 0
       -        }
       -        if start > len(aStr) {
       -                return "", errors.New(fmt.Sprintf("start position out of bounds for %d-byte string", len(aStr)))
       -        }
       -
       -        var s, e int
       -        if start >= 0 && length >= 0 {
       -                s = start
       -                e = start + length
       -        } else if start < 0 && length >= 0 {
       -                s = len(aStr) + start - length + 1
       -                e = len(aStr) + start + 1
       -        } else if start >= 0 && length < 0 {
       -                s = start
       -                e = len(aStr) + length
       -        } else {
       -                s = len(aStr) + start
       -                e = len(aStr) + length
       -        }
       -
       -        if s > e {
       -                return "", errors.New(fmt.Sprintf("calculated start position greater than end position: %d > %d", s, e))
       -        }
       -        if e > len(aStr) {
       -                e = len(aStr)
       -        }
       -
       -        return aStr[s:e], nil
       -
       -}
       -
       -func Split(a interface{}, delimiter string) ([]string, error) {
       -        aStr, err := cast.ToStringE(a)
       -        if err != nil {
       -                return []string{}, err
       -        }
       -        return strings.Split(aStr, delimiter), nil
       -}
       -
       -func Intersect(l1, l2 interface{}) (interface{}, error) {
       -        if l1 == nil || l2 == nil {
       -                return make([]interface{}, 0), nil
       -        }
       -
       -        l1v := reflect.ValueOf(l1)
       -        l2v := reflect.ValueOf(l2)
       -
       -        switch l1v.Kind() {
       -        case reflect.Array, reflect.Slice:
       -                switch l2v.Kind() {
       -                case reflect.Array, reflect.Slice:
       -                        r := reflect.MakeSlice(l1v.Type(), 0, 0)
       -                        for i := 0; i < l1v.Len(); i++ {
       -                                l1vv := l1v.Index(i)
       -                                for j := 0; j < l2v.Len(); j++ {
       -                                        l2vv := l2v.Index(j)
       -                                        switch l1vv.Kind() {
       -                                        case reflect.String:
       -                                                if l1vv.Type() == l2vv.Type() && l1vv.String() == l2vv.String() && !In(r, l2vv) {
       -                                                        r = reflect.Append(r, l2vv)
       -                                                }
       -                                        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                                                switch l2vv.Kind() {
       -                                                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                                                        if l1vv.Int() == l2vv.Int() && !In(r, l2vv) {
       -                                                                r = reflect.Append(r, l2vv)
       -                                                        }
       -                                                }
       -                                        case reflect.Float32, reflect.Float64:
       -                                                switch l2vv.Kind() {
       -                                                case reflect.Float32, reflect.Float64:
       -                                                        if l1vv.Float() == l2vv.Float() && !In(r, l2vv) {
       -                                                                r = reflect.Append(r, l2vv)
       -                                                        }
       -                                                }
       -                                        }
       -                                }
       -                        }
       -                        return r.Interface(), nil
       -                default:
       -                        return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String())
       -                }
       -        default:
       -                return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
       -        }
       -}
       -
       -func In(l interface{}, v interface{}) bool {
       -        lv := reflect.ValueOf(l)
       -        vv := reflect.ValueOf(v)
       -
       -        switch lv.Kind() {
       -        case reflect.Array, reflect.Slice:
       -                for i := 0; i < lv.Len(); i++ {
       -                        lvv := lv.Index(i)
       -                        switch lvv.Kind() {
       -                        case reflect.String:
       -                                if vv.Type() == lvv.Type() && vv.String() == lvv.String() {
       -                                        return true
       -                                }
       -                        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                                switch vv.Kind() {
       -                                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                                        if vv.Int() == lvv.Int() {
       -                                                return true
       -                                        }
       -                                }
       -                        case reflect.Float32, reflect.Float64:
       -                                switch vv.Kind() {
       -                                case reflect.Float32, reflect.Float64:
       -                                        if vv.Float() == lvv.Float() {
       -                                                return true
       -                                        }
       -                                }
       -                        }
       -                }
       -        case reflect.String:
       -                if vv.Type() == lv.Type() && strings.Contains(lv.String(), vv.String()) {
       -                        return true
       -                }
       -        }
       -        return false
       -}
       -
       -// indirect is taken from 'text/template/exec.go'
       -func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
       -        for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
       -                if v.IsNil() {
       -                        return v, true
       -                }
       -                if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
       -                        break
       -                }
       -        }
       -        return v, false
       -}
       -
       -// First is exposed to templates, to iterate over the first N items in a
       -// rangeable list.
       -func First(limit interface{}, seq interface{}) (interface{}, error) {
       -
       -        if limit == nil || seq == nil {
       -                return nil, errors.New("both limit and seq must be provided")
       -        }
       -
       -        limitv, err := cast.ToIntE(limit)
       -
       -        if err != nil {
       -                return nil, err
       -        }
       -
       -        if limitv < 1 {
       -                return nil, errors.New("can't return negative/empty count of items from sequence")
       -        }
       -
       -        seqv := reflect.ValueOf(seq)
       -        seqv, isNil := indirect(seqv)
       -        if isNil {
       -                return nil, errors.New("can't iterate over a nil value")
       -        }
       -
       -        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 limitv > seqv.Len() {
       -                limitv = seqv.Len()
       -        }
       -        return seqv.Slice(0, limitv).Interface(), nil
       -}
       -
       -var (
       -        zero      reflect.Value
       -        errorType = reflect.TypeOf((*error)(nil)).Elem()
       -)
       -
       -func evaluateSubElem(obj reflect.Value, elemName string) (reflect.Value, error) {
       -        if !obj.IsValid() {
       -                return zero, errors.New("can't evaluate an invalid value")
       -        }
       -        typ := obj.Type()
       -        obj, isNil := indirect(obj)
       -
       -        // first, check whether obj has a method. In this case, obj is
       -        // an interface, a struct or its pointer. If obj is a struct,
       -        // to check all T and *T method, use obj pointer type Value
       -        objPtr := obj
       -        if objPtr.Kind() != reflect.Interface && objPtr.CanAddr() {
       -                objPtr = objPtr.Addr()
       -        }
       -        mt, ok := objPtr.Type().MethodByName(elemName)
       -        if ok {
       -                if mt.PkgPath != "" {
       -                        return zero, fmt.Errorf("%s is an unexported method of type %s", elemName, typ)
       -                }
       -                // struct pointer has one receiver argument and interface doesn't have an argument
       -                if mt.Type.NumIn() > 1 || mt.Type.NumOut() == 0 || mt.Type.NumOut() > 2 {
       -                        return zero, fmt.Errorf("%s is a method of type %s but doesn't satisfy requirements", elemName, typ)
       -                }
       -                if mt.Type.NumOut() == 1 && mt.Type.Out(0).Implements(errorType) {
       -                        return zero, fmt.Errorf("%s is a method of type %s but doesn't satisfy requirements", elemName, typ)
       -                }
       -                if mt.Type.NumOut() == 2 && !mt.Type.Out(1).Implements(errorType) {
       -                        return zero, fmt.Errorf("%s is a method of type %s but doesn't satisfy requirements", elemName, typ)
       -                }
       -                res := objPtr.Method(mt.Index).Call([]reflect.Value{})
       -                if len(res) == 2 && !res[1].IsNil() {
       -                        return zero, fmt.Errorf("error at calling a method %s of type %s: %s", elemName, typ, res[1].Interface().(error))
       -                }
       -                return res[0], nil
       -        }
       -
       -        // elemName isn't a method so next start to check whether it is
       -        // a struct field or a map value. In both cases, it mustn't be
       -        // a nil value
       -        if isNil {
       -                return zero, fmt.Errorf("can't evaluate a nil pointer of type %s by a struct field or map key name %s", typ, elemName)
       -        }
       -        switch obj.Kind() {
       -        case reflect.Struct:
       -                ft, ok := obj.Type().FieldByName(elemName)
       -                if ok {
       -                        if ft.PkgPath != "" {
       -                                return zero, fmt.Errorf("%s is an unexported field of struct type %s", elemName, typ)
       -                        }
       -                        return obj.FieldByIndex(ft.Index), nil
       -                }
       -                return zero, fmt.Errorf("%s isn't a field of struct type %s", elemName, typ)
       -        case reflect.Map:
       -                kv := reflect.ValueOf(elemName)
       -                if kv.Type().AssignableTo(obj.Type().Key()) {
       -                        return obj.MapIndex(kv), nil
       -                }
       -                return zero, fmt.Errorf("%s isn't a key of map type %s", elemName, typ)
       -        }
       -        return zero, fmt.Errorf("%s is neither a struct field, a method nor a map element of type %s", elemName, typ)
       -}
       -
       -func checkCondition(v, mv reflect.Value, op string) (bool, error) {
       -        if !v.IsValid() || !mv.IsValid() {
       -                return false, nil
       -        }
       -
       -        var isNil bool
       -        v, isNil = indirect(v)
       -        if isNil {
       -                return false, nil
       -        }
       -        mv, isNil = indirect(mv)
       -        if isNil {
       -                return false, nil
       -        }
       -
       -        var ivp, imvp *int64
       -        var svp, smvp *string
       -        var ima []int64
       -        var sma []string
       -        if mv.Type() == v.Type() {
       -                switch v.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        iv := v.Int()
       -                        ivp = &iv
       -                        imv := mv.Int()
       -                        imvp = &imv
       -                case reflect.String:
       -                        sv := v.String()
       -                        svp = &sv
       -                        smv := mv.String()
       -                        smvp = &smv
       -                }
       -        } else {
       -                if mv.Kind() != reflect.Array && mv.Kind() != reflect.Slice {
       -                        return false, nil
       -                }
       -                if mv.Type().Elem() != v.Type() {
       -                        return false, nil
       -                }
       -                switch v.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        iv := v.Int()
       -                        ivp = &iv
       -                        for i := 0; i < mv.Len(); i++ {
       -                                ima = append(ima, mv.Index(i).Int())
       -                        }
       -                case reflect.String:
       -                        sv := v.String()
       -                        svp = &sv
       -                        for i := 0; i < mv.Len(); i++ {
       -                                sma = append(sma, mv.Index(i).String())
       -                        }
       -                }
       -        }
       -
       -        switch op {
       -        case "", "=", "==", "eq":
       -                if ivp != nil && imvp != nil {
       -                        return *ivp == *imvp, nil
       -                } else if svp != nil && smvp != nil {
       -                        return *svp == *smvp, nil
       -                }
       -        case "!=", "<>", "ne":
       -                if ivp != nil && imvp != nil {
       -                        return *ivp != *imvp, nil
       -                } else if svp != nil && smvp != nil {
       -                        return *svp != *smvp, nil
       -                }
       -        case ">=", "ge":
       -                if ivp != nil && imvp != nil {
       -                        return *ivp >= *imvp, nil
       -                } else if svp != nil && smvp != nil {
       -                        return *svp >= *smvp, nil
       -                }
       -        case ">", "gt":
       -                if ivp != nil && imvp != nil {
       -                        return *ivp > *imvp, nil
       -                } else if svp != nil && smvp != nil {
       -                        return *svp > *smvp, nil
       -                }
       -        case "<=", "le":
       -                if ivp != nil && imvp != nil {
       -                        return *ivp <= *imvp, nil
       -                } else if svp != nil && smvp != nil {
       -                        return *svp <= *smvp, nil
       -                }
       -        case "<", "lt":
       -                if ivp != nil && imvp != nil {
       -                        return *ivp < *imvp, nil
       -                } else if svp != nil && smvp != nil {
       -                        return *svp < *smvp, nil
       -                }
       -        case "in", "not in":
       -                var r bool
       -                if ivp != nil && len(ima) > 0 {
       -                        r = In(ima, *ivp)
       -                } else if svp != nil {
       -                        if len(sma) > 0 {
       -                                r = In(sma, *svp)
       -                        } else if smvp != nil {
       -                                r = In(*smvp, *svp)
       -                        }
       -                } else {
       -                        return false, nil
       -                }
       -                if op == "not in" {
       -                        return !r, nil
       -                } else {
       -                        return r, nil
       -                }
       -        default:
       -                return false, errors.New("no such an operator")
       -        }
       -        return false, nil
       -}
       -
       -func Where(seq, key interface{}, args ...interface{}) (r interface{}, err error) {
       -        seqv := reflect.ValueOf(seq)
       -        kv := reflect.ValueOf(key)
       -
       -        var mv reflect.Value
       -        var op string
       -        switch len(args) {
       -        case 1:
       -                mv = reflect.ValueOf(args[0])
       -        case 2:
       -                var ok bool
       -                if op, ok = args[0].(string); !ok {
       -                        return nil, errors.New("operator argument must be string type")
       -                }
       -                op = strings.TrimSpace(strings.ToLower(op))
       -                mv = reflect.ValueOf(args[1])
       -        default:
       -                return nil, errors.New("can't evaluate the array by no match argument or more than or equal to two arguments")
       -        }
       -
       -        seqv, isNil := indirect(seqv)
       -        if isNil {
       -                return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(seq).Type().String())
       -        }
       -
       -        var path []string
       -        if kv.Kind() == reflect.String {
       -                path = strings.Split(strings.Trim(kv.String(), "."), ".")
       -        }
       -
       -        switch seqv.Kind() {
       -        case reflect.Array, reflect.Slice:
       -                rv := reflect.MakeSlice(seqv.Type(), 0, 0)
       -                for i := 0; i < seqv.Len(); i++ {
       -                        var vvv reflect.Value
       -                        rvv := seqv.Index(i)
       -                        if kv.Kind() == reflect.String {
       -                                vvv = rvv
       -                                for _, elemName := range path {
       -                                        vvv, err = evaluateSubElem(vvv, elemName)
       -                                        if err != nil {
       -                                                return nil, err
       -                                        }
       -                                }
       -                        } else {
       -                                vv, _ := indirect(rvv)
       -                                if vv.Kind() == reflect.Map && kv.Type().AssignableTo(vv.Type().Key()) {
       -                                        vvv = vv.MapIndex(kv)
       -                                }
       -                        }
       -                        if ok, err := checkCondition(vvv, mv, op); ok {
       -                                rv = reflect.Append(rv, rvv)
       -                        } else if err != nil {
       -                                return nil, err
       -                        }
       -                }
       -                return rv.Interface(), nil
       -        default:
       -                return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
       -        }
       -}
       -
       -// Apply, given a map, array, or slice, returns a new slice with the function fname applied over it.
       -func Apply(seq interface{}, fname string, args ...interface{}) (interface{}, error) {
       -        if seq == nil {
       -                return make([]interface{}, 0), nil
       -        }
       -
       -        if fname == "apply" {
       -                return nil, errors.New("can't apply myself (no turtles allowed)")
       -        }
       -
       -        seqv := reflect.ValueOf(seq)
       -        seqv, isNil := indirect(seqv)
       -        if isNil {
       -                return nil, errors.New("can't iterate over a nil value")
       -        }
       -
       -        fn, found := funcMap[fname]
       -        if !found {
       -                return nil, errors.New("can't find function " + fname)
       -        }
       -
       -        fnv := reflect.ValueOf(fn)
       -
       -        switch seqv.Kind() {
       -        case reflect.Array, reflect.Slice:
       -                r := make([]interface{}, seqv.Len())
       -                for i := 0; i < seqv.Len(); i++ {
       -                        vv := seqv.Index(i)
       -
       -                        vvv, err := applyFnToThis(fnv, vv, args...)
       -
       -                        if err != nil {
       -                                return nil, err
       -                        }
       -
       -                        r[i] = vvv.Interface()
       -                }
       -
       -                return r, nil
       -        default:
       -                return nil, errors.New("can't apply over " + reflect.ValueOf(seq).Type().String())
       -        }
       -}
       -
       -func applyFnToThis(fn, this reflect.Value, args ...interface{}) (reflect.Value, error) {
       -        n := make([]reflect.Value, len(args))
       -        for i, arg := range args {
       -                if arg == "." {
       -                        n[i] = this
       -                } else {
       -                        n[i] = reflect.ValueOf(arg)
       -                }
       -        }
       -
       -        res := fn.Call(n)
       -
       -        if len(res) == 1 || res[1].IsNil() {
       -                return res[0], nil
       -        } else {
       -                return reflect.ValueOf(nil), res[1].Interface().(error)
       -        }
       -}
       -
       -func Delimit(seq, delimiter interface{}, last ...interface{}) (template.HTML, error) {
       -        d, err := cast.ToStringE(delimiter)
       -        if err != nil {
       -                return "", err
       -        }
       -
       -        var dLast *string
       -        for _, l := range last {
       -                dStr, err := cast.ToStringE(l)
       -                if err != nil {
       -                        dLast = nil
       -                }
       -                dLast = &dStr
       -                break
       -        }
       -
       -        seqv := reflect.ValueOf(seq)
       -        seqv, isNil := indirect(seqv)
       -        if isNil {
       -                return "", errors.New("can't iterate over a nil value")
       -        }
       -
       -        var str string
       -        switch seqv.Kind() {
       -        case reflect.Map:
       -                sortSeq, err := Sort(seq)
       -                if err != nil {
       -                        return "", err
       -                }
       -                seqv = reflect.ValueOf(sortSeq)
       -                fallthrough
       -        case reflect.Array, reflect.Slice, reflect.String:
       -                for i := 0; i < seqv.Len(); i++ {
       -                        val := seqv.Index(i).Interface()
       -                        valStr, err := cast.ToStringE(val)
       -                        if err != nil {
       -                                continue
       -                        }
       -                        switch {
       -                        case i == seqv.Len()-2 && dLast != nil:
       -                                str += valStr + *dLast
       -                        case i == seqv.Len()-1:
       -                                str += valStr
       -                        default:
       -                                str += valStr + d
       -                        }
       -                }
       -
       -        default:
       -                return "", errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
       -        }
       -
       -        return template.HTML(str), nil
       -}
       -
       -func Sort(seq interface{}, args ...interface{}) ([]interface{}, error) {
       -        seqv := reflect.ValueOf(seq)
       -        seqv, isNil := indirect(seqv)
       -        if isNil {
       -                return nil, errors.New("can't iterate over a nil value")
       -        }
       -
       -        // Create a list of pairs that will be used to do the sort
       -        p := pairList{SortAsc: true}
       -        p.Pairs = make([]pair, seqv.Len())
       -
       -        for i, l := range args {
       -                dStr, err := cast.ToStringE(l)
       -                switch {
       -                case i == 0 && err != nil:
       -                        p.SortByField = ""
       -                case i == 0 && err == nil:
       -                        p.SortByField = dStr
       -                case i == 1 && err == nil && dStr == "desc":
       -                        p.SortAsc = false
       -                case i == 1:
       -                        p.SortAsc = true
       -                }
       -        }
       -
       -        var sorted []interface{}
       -        switch seqv.Kind() {
       -        case reflect.Array, reflect.Slice:
       -                for i := 0; i < seqv.Len(); i++ {
       -                        p.Pairs[i].Key = reflect.ValueOf(i)
       -                        p.Pairs[i].Value = seqv.Index(i)
       -                }
       -                if p.SortByField == "" {
       -                        p.SortByField = "value"
       -                }
       -
       -        case reflect.Map:
       -                keys := seqv.MapKeys()
       -                for i := 0; i < seqv.Len(); i++ {
       -                        p.Pairs[i].Key = keys[i]
       -                        p.Pairs[i].Value = seqv.MapIndex(keys[i])
       -                }
       -
       -        default:
       -                return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String())
       -        }
       -        sorted = p.sort()
       -        return sorted, nil
       -}
       -
       -// Credit for pair sorting method goes to Andrew Gerrand
       -// https://groups.google.com/forum/#!topic/golang-nuts/FT7cjmcL7gw
       -// A data structure to hold a key/value pair.
       -type pair struct {
       -        Key   reflect.Value
       -        Value reflect.Value
       -}
       -
       -// A slice of pairs that implements sort.Interface to sort by Value.
       -type pairList struct {
       -        Pairs       []pair
       -        SortByField string
       -        SortAsc     bool
       -}
       -
       -func (p pairList) Swap(i, j int) { p.Pairs[i], p.Pairs[j] = p.Pairs[j], p.Pairs[i] }
       -func (p pairList) Len() int      { return len(p.Pairs) }
       -func (p pairList) Less(i, j int) bool {
       -        var truth bool
       -        switch {
       -        case p.SortByField == "value":
       -                iVal := p.Pairs[i].Value
       -                jVal := p.Pairs[j].Value
       -                truth = Lt(iVal.Interface(), jVal.Interface())
       -
       -        case p.SortByField != "":
       -                if p.Pairs[i].Value.FieldByName(p.SortByField).IsValid() {
       -                        iVal := p.Pairs[i].Value.FieldByName(p.SortByField)
       -                        jVal := p.Pairs[j].Value.FieldByName(p.SortByField)
       -                        truth = Lt(iVal.Interface(), jVal.Interface())
       -                }
       -        default:
       -                iVal := p.Pairs[i].Key
       -                jVal := p.Pairs[j].Key
       -                truth = Lt(iVal.Interface(), jVal.Interface())
       -        }
       -        return truth
       -}
       -
       -// sorts a pairList and returns a slice of sorted values
       -func (p pairList) sort() []interface{} {
       -        if p.SortAsc {
       -                sort.Sort(p)
       -        } else {
       -                sort.Sort(sort.Reverse(p))
       -        }
       -        sorted := make([]interface{}, len(p.Pairs))
       -        for i, v := range p.Pairs {
       -                sorted[i] = v.Value.Interface()
       -        }
       -
       -        return sorted
       -}
       -
       -func IsSet(a interface{}, key interface{}) bool {
       -        av := reflect.ValueOf(a)
       -        kv := reflect.ValueOf(key)
       -
       -        switch av.Kind() {
       -        case reflect.Array, reflect.Chan, reflect.Slice:
       -                if int64(av.Len()) > kv.Int() {
       -                        return true
       -                }
       -        case reflect.Map:
       -                if kv.Type() == av.Type().Key() {
       -                        return av.MapIndex(kv).IsValid()
       -                }
       -        }
       -
       -        return false
       -}
       -
       -func ReturnWhenSet(a, k interface{}) interface{} {
       -        av, isNil := indirect(reflect.ValueOf(a))
       -        if isNil {
       -                return ""
       -        }
       -
       -        var avv reflect.Value
       -        switch av.Kind() {
       -        case reflect.Array, reflect.Slice:
       -                index, ok := k.(int)
       -                if ok && av.Len() > index {
       -                        avv = av.Index(index)
       -                }
       -        case reflect.Map:
       -                kv := reflect.ValueOf(k)
       -                if kv.Type().AssignableTo(av.Type().Key()) {
       -                        avv = av.MapIndex(kv)
       -                }
       -        }
       -
       -        if avv.IsValid() {
       -                switch avv.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        return avv.Int()
       -                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       -                        return avv.Uint()
       -                case reflect.Float32, reflect.Float64:
       -                        return avv.Float()
       -                case reflect.String:
       -                        return avv.String()
       -                }
       -        }
       -
       -        return ""
       -}
       -
       -func Highlight(in interface{}, lang string) template.HTML {
       -        var str string
       -        av := reflect.ValueOf(in)
       -        switch av.Kind() {
       -        case reflect.String:
       -                str = av.String()
       -        }
       -
       -        return template.HTML(helpers.Highlight(html.UnescapeString(str), lang))
       -}
       -
       -var markdownTrimPrefix = []byte("<p>")
       -var markdownTrimSuffix = []byte("</p>\n")
       -
       -func Markdownify(text string) template.HTML {
       -        m := helpers.RenderBytes(&helpers.RenderingContext{Content: []byte(text), PageFmt: "markdown"})
       -        m = bytes.TrimPrefix(m, markdownTrimPrefix)
       -        m = bytes.TrimSuffix(m, markdownTrimSuffix)
       -        return template.HTML(m)
       -}
       -
       -func refPage(page interface{}, ref, methodName string) template.HTML {
       -        value := reflect.ValueOf(page)
       -
       -        method := value.MethodByName(methodName)
       -
       -        if method.IsValid() && method.Type().NumIn() == 1 && method.Type().NumOut() == 2 {
       -                result := method.Call([]reflect.Value{reflect.ValueOf(ref)})
       -
       -                url, err := result[0], result[1]
       -
       -                if !err.IsNil() {
       -                        jww.ERROR.Printf("%s", err.Interface())
       -                        return template.HTML(fmt.Sprintf("%s", err.Interface()))
       -                }
       -
       -                if url.String() == "" {
       -                        jww.ERROR.Printf("ref %s could not be found\n", ref)
       -                        return template.HTML(ref)
       -                }
       -
       -                return template.HTML(url.String())
       -        }
       -
       -        jww.ERROR.Printf("Can only create references from Page and Node objects.")
       -        return template.HTML(ref)
       -}
       -
       -func Ref(page interface{}, ref string) template.HTML {
       -        return refPage(page, ref, "Ref")
       -}
       -
       -func RelRef(page interface{}, ref string) template.HTML {
       -        return refPage(page, ref, "RelRef")
       -}
       -
       -func Chomp(text interface{}) (string, error) {
       -        s, err := cast.ToStringE(text)
       -        if err != nil {
       -                return "", err
       -        }
       -
       -        return strings.TrimRight(s, "\r\n"), nil
       -}
       -
       -// Trim leading/trailing characters defined by b from a
       -func Trim(a interface{}, b string) (string, error) {
       -        aStr, err := cast.ToStringE(a)
       -        if err != nil {
       -                return "", err
       -        }
       -        return strings.Trim(aStr, b), nil
       -}
       -
       -// Replace all occurences of b with c in a
       -func Replace(a, b, c interface{}) (string, error) {
       -        aStr, err := cast.ToStringE(a)
       -        if err != nil {
       -                return "", err
       -        }
       -        bStr, err := cast.ToStringE(b)
       -        if err != nil {
       -                return "", err
       -        }
       -        cStr, err := cast.ToStringE(c)
       -        if err != nil {
       -                return "", err
       -        }
       -        return strings.Replace(aStr, bStr, cStr, -1), nil
       -}
       -
       -// DateFormat converts the textual representation of the datetime string into
       -// the other form or returns it of the time.Time value. These are formatted
       -// with the layout string
       -func DateFormat(layout string, v interface{}) (string, error) {
       -        t, err := cast.ToTimeE(v)
       -        if err != nil {
       -                return "", err
       -        }
       -        return t.Format(layout), nil
       -}
       -
       -func SafeHTML(text string) template.HTML {
       -        return template.HTML(text)
       -}
       -
       -// "safeHTMLAttr" is currently disabled, pending further discussion
       -// on its use case.  2015-01-19
       -func SafeHTMLAttr(text string) template.HTMLAttr {
       -        return template.HTMLAttr(text)
       -}
       -
       -func SafeCSS(text string) template.CSS {
       -        return template.CSS(text)
       -}
       -
       -func SafeURL(text string) template.URL {
       -        return template.URL(text)
       -}
       -
       -func doArithmetic(a, b interface{}, op rune) (interface{}, error) {
       -        av := reflect.ValueOf(a)
       -        bv := reflect.ValueOf(b)
       -        var ai, bi int64
       -        var af, bf float64
       -        var au, bu uint64
       -        switch av.Kind() {
       -        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                ai = av.Int()
       -                switch bv.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        bi = bv.Int()
       -                case reflect.Float32, reflect.Float64:
       -                        af = float64(ai) // may overflow
       -                        ai = 0
       -                        bf = bv.Float()
       -                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       -                        bu = bv.Uint()
       -                        if ai >= 0 {
       -                                au = uint64(ai)
       -                                ai = 0
       -                        } else {
       -                                bi = int64(bu) // may overflow
       -                                bu = 0
       -                        }
       -                default:
       -                        return nil, errors.New("Can't apply the operator to the values")
       -                }
       -        case reflect.Float32, reflect.Float64:
       -                af = av.Float()
       -                switch bv.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        bf = float64(bv.Int()) // may overflow
       -                case reflect.Float32, reflect.Float64:
       -                        bf = bv.Float()
       -                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       -                        bf = float64(bv.Uint()) // may overflow
       -                default:
       -                        return nil, errors.New("Can't apply the operator to the values")
       -                }
       -        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       -                au = av.Uint()
       -                switch bv.Kind() {
       -                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                        bi = bv.Int()
       -                        if bi >= 0 {
       -                                bu = uint64(bi)
       -                                bi = 0
       -                        } else {
       -                                ai = int64(au) // may overflow
       -                                au = 0
       -                        }
       -                case reflect.Float32, reflect.Float64:
       -                        af = float64(au) // may overflow
       -                        au = 0
       -                        bf = bv.Float()
       -                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       -                        bu = bv.Uint()
       -                default:
       -                        return nil, errors.New("Can't apply the operator to the values")
       -                }
       -        case reflect.String:
       -                as := av.String()
       -                if bv.Kind() == reflect.String && op == '+' {
       -                        bs := bv.String()
       -                        return as + bs, nil
       -                } else {
       -                        return nil, errors.New("Can't apply the operator to the values")
       -                }
       -        default:
       -                return nil, errors.New("Can't apply the operator to the values")
       -        }
       -
       -        switch op {
       -        case '+':
       -                if ai != 0 || bi != 0 {
       -                        return ai + bi, nil
       -                } else if af != 0 || bf != 0 {
       -                        return af + bf, nil
       -                } else if au != 0 || bu != 0 {
       -                        return au + bu, nil
       -                } else {
       -                        return 0, nil
       -                }
       -        case '-':
       -                if ai != 0 || bi != 0 {
       -                        return ai - bi, nil
       -                } else if af != 0 || bf != 0 {
       -                        return af - bf, nil
       -                } else if au != 0 || bu != 0 {
       -                        return au - bu, nil
       -                } else {
       -                        return 0, nil
       -                }
       -        case '*':
       -                if ai != 0 || bi != 0 {
       -                        return ai * bi, nil
       -                } else if af != 0 || bf != 0 {
       -                        return af * bf, nil
       -                } else if au != 0 || bu != 0 {
       -                        return au * bu, nil
       -                } else {
       -                        return 0, nil
       -                }
       -        case '/':
       -                if bi != 0 {
       -                        return ai / bi, nil
       -                } else if bf != 0 {
       -                        return af / bf, nil
       -                } else if bu != 0 {
       -                        return au / bu, nil
       -                } else {
       -                        return nil, errors.New("Can't divide the value by 0")
       -                }
       -        default:
       -                return nil, errors.New("There is no such an operation")
       -        }
       -}
       -
       -func Mod(a, b interface{}) (int64, error) {
       -        av := reflect.ValueOf(a)
       -        bv := reflect.ValueOf(b)
       -        var ai, bi int64
       -
       -        switch av.Kind() {
       -        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                ai = av.Int()
       -        default:
       -                return 0, errors.New("Modulo operator can't be used with non integer value")
       -        }
       -
       -        switch bv.Kind() {
       -        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       -                bi = bv.Int()
       -        default:
       -                return 0, errors.New("Modulo operator can't be used with non integer value")
       -        }
       -
       -        if bi == 0 {
       -                return 0, errors.New("The number can't be divided by zero at modulo operation")
       -        }
       -
       -        return ai % bi, nil
       -}
       -
       -func ModBool(a, b interface{}) (bool, error) {
       -        res, err := Mod(a, b)
       -        if err != nil {
       -                return false, err
       -        }
       -        return res == int64(0), nil
       -}
       -
        func Partial(name string, context_list ...interface{}) template.HTML {
                if strings.HasPrefix("partials/", name) {
                        name = name[8:]
       @@ -1351,8 +226,6 @@ func isBackupFile(path string) bool {
                return path[len(path)-1] == '~'
        }
        
       -// TODO(bep) split this file in two => template_funcs.go + tests.
       -
        const baseAceFilename = "baseof.ace"
        
        var aceTemplateInnerMarker = []byte("= content")
       @@ -1441,82 +314,3 @@ func (t *GoHTMLTemplate) PrintErrors() {
                        jww.ERROR.Println(e.err)
                }
        }
       -
       -func init() {
       -        funcMap = template.FuncMap{
       -                "urlize":      helpers.URLize,
       -                "sanitizeURL": helpers.SanitizeURL,
       -                "sanitizeurl": helpers.SanitizeURL,
       -                "eq":          Eq,
       -                "ne":          Ne,
       -                "gt":          Gt,
       -                "ge":          Ge,
       -                "lt":          Lt,
       -                "le":          Le,
       -                "in":          In,
       -                "slicestr":    Slicestr,
       -                "substr":      Substr,
       -                "split":       Split,
       -                "intersect":   Intersect,
       -                "isSet":       IsSet,
       -                "isset":       IsSet,
       -                "echoParam":   ReturnWhenSet,
       -                "safeHTML":    SafeHTML,
       -                "safeCSS":     SafeCSS,
       -                "safeURL":     SafeURL,
       -                "markdownify": Markdownify,
       -                "first":       First,
       -                "where":       Where,
       -                "delimit":     Delimit,
       -                "sort":        Sort,
       -                "highlight":   Highlight,
       -                "add":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
       -                "sub":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
       -                "div":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
       -                "mod":         Mod,
       -                "mul":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
       -                "modBool":     ModBool,
       -                "lower":       func(a string) string { return strings.ToLower(a) },
       -                "upper":       func(a string) string { return strings.ToUpper(a) },
       -                "title":       func(a string) string { return strings.Title(a) },
       -                "partial":     Partial,
       -                "ref":         Ref,
       -                "relref":      RelRef,
       -                "apply":       Apply,
       -                "chomp":       Chomp,
       -                "replace":     Replace,
       -                "trim":        Trim,
       -                "dateFormat":  DateFormat,
       -                "getJSON":     GetJSON,
       -                "getCSV":      GetCSV,
       -                "seq":         helpers.Seq,
       -                "getenv":      func(varName string) string { return os.Getenv(varName) },
       -
       -                // "getJson" is deprecated. Will be removed in 0.15.
       -                "getJson": func(urlParts ...string) interface{} {
       -                        helpers.Deprecated("Template", "getJson", "getJSON")
       -                        return GetJSON(urlParts...)
       -                },
       -                // "getJson" is deprecated. Will be removed in 0.15.
       -                "getCsv": func(sep string, urlParts ...string) [][]string {
       -                        helpers.Deprecated("Template", "getCsv", "getCSV")
       -                        return GetCSV(sep, urlParts...)
       -                },
       -                // "safeHtml" is deprecated. Will be removed in 0.15.
       -                "safeHtml": func(text string) template.HTML {
       -                        helpers.Deprecated("Template", "safeHtml", "safeHTML")
       -                        return SafeHTML(text)
       -                },
       -                // "safeCss" is deprecated. Will be removed in 0.15.
       -                "safeCss": func(text string) template.CSS {
       -                        helpers.Deprecated("Template", "safeCss", "safeCSS")
       -                        return SafeCSS(text)
       -                },
       -                // "safeUrl" is deprecated. Will be removed in 0.15.
       -                "safeUrl": func(text string) template.URL {
       -                        helpers.Deprecated("Template", "safeUrl", "safeURL")
       -                        return SafeURL(text)
       -                },
       -        }
       -
       -}
 (DIR) diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go
       @@ -0,0 +1,1228 @@
       +// Copyright © 2013-14 Steve Francia <spf@spf13.com>.
       +//
       +// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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 tpl
       +
       +import (
       +        "bytes"
       +        "errors"
       +        "fmt"
       +        "github.com/spf13/cast"
       +        "github.com/spf13/hugo/helpers"
       +        jww "github.com/spf13/jwalterweatherman"
       +        "html"
       +        "html/template"
       +        "os"
       +        "reflect"
       +        "sort"
       +        "strconv"
       +        "strings"
       +)
       +
       +var funcMap template.FuncMap
       +
       +func Eq(x, y interface{}) bool {
       +        normalize := func(v interface{}) interface{} {
       +                vv := reflect.ValueOf(v)
       +                switch vv.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        return vv.Int()
       +                case reflect.Float32, reflect.Float64:
       +                        return vv.Float()
       +                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       +                        return vv.Uint()
       +                default:
       +                        return v
       +                }
       +        }
       +        x = normalize(x)
       +        y = normalize(y)
       +        return reflect.DeepEqual(x, y)
       +}
       +
       +func Ne(x, y interface{}) bool {
       +        return !Eq(x, y)
       +}
       +
       +func Ge(a, b interface{}) bool {
       +        left, right := compareGetFloat(a, b)
       +        return left >= right
       +}
       +
       +func Gt(a, b interface{}) bool {
       +        left, right := compareGetFloat(a, b)
       +        return left > right
       +}
       +
       +func Le(a, b interface{}) bool {
       +        left, right := compareGetFloat(a, b)
       +        return left <= right
       +}
       +
       +func Lt(a, b interface{}) bool {
       +        left, right := compareGetFloat(a, b)
       +        return left < right
       +}
       +
       +func compareGetFloat(a interface{}, b interface{}) (float64, float64) {
       +        var left, right float64
       +        var leftStr, rightStr *string
       +        var err error
       +        av := reflect.ValueOf(a)
       +
       +        switch av.Kind() {
       +        case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
       +                left = float64(av.Len())
       +        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                left = float64(av.Int())
       +        case reflect.Float32, reflect.Float64:
       +                left = av.Float()
       +        case reflect.String:
       +                left, err = strconv.ParseFloat(av.String(), 64)
       +                if err != nil {
       +                        str := av.String()
       +                        leftStr = &str
       +                }
       +        }
       +
       +        bv := reflect.ValueOf(b)
       +
       +        switch bv.Kind() {
       +        case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
       +                right = float64(bv.Len())
       +        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                right = float64(bv.Int())
       +        case reflect.Float32, reflect.Float64:
       +                right = bv.Float()
       +        case reflect.String:
       +                right, err = strconv.ParseFloat(bv.String(), 64)
       +                if err != nil {
       +                        str := bv.String()
       +                        rightStr = &str
       +                }
       +
       +        }
       +
       +        switch {
       +        case leftStr == nil || rightStr == nil:
       +        case *leftStr < *rightStr:
       +                return 0, 1
       +        case *leftStr > *rightStr:
       +                return 1, 0
       +        default:
       +                return 0, 0
       +        }
       +
       +        return left, right
       +}
       +
       +// Slicing in Slicestr is done by specifying a half-open range with
       +// two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
       +// The end index can be omitted, it defaults to the string's length.
       +func Slicestr(a interface{}, startEnd ...int) (string, error) {
       +        aStr, err := cast.ToStringE(a)
       +        if err != nil {
       +                return "", err
       +        }
       +
       +        if len(startEnd) > 2 {
       +                return "", errors.New("too many arguments")
       +        }
       +
       +        if len(startEnd) == 2 {
       +                return aStr[startEnd[0]:startEnd[1]], nil
       +        } else if len(startEnd) == 1 {
       +                return aStr[startEnd[0]:], nil
       +        } else {
       +                return aStr[:], nil
       +        }
       +
       +}
       +
       +// Substr extracts parts of a string, beginning at the character at the specified
       +// position, and returns the specified number of characters.
       +//
       +// It normally takes two parameters: start and length.
       +// It can also take one parameter: start, i.e. length is omitted, in which case
       +// the substring starting from start until the end of the string will be returned.
       +//
       +// To extract characters from the end of the string, use a negative start number.
       +//
       +// In addition, borrowing from the extended behavior described at http://php.net/substr,
       +// if length is given and is negative, then that many characters will be omitted from
       +// the end of string.
       +func Substr(a interface{}, nums ...int) (string, error) {
       +        aStr, err := cast.ToStringE(a)
       +        if err != nil {
       +                return "", err
       +        }
       +
       +        var start, length int
       +        switch len(nums) {
       +        case 1:
       +                start = nums[0]
       +                length = len(aStr)
       +        case 2:
       +                start = nums[0]
       +                length = nums[1]
       +        default:
       +                return "", errors.New("too many arguments")
       +        }
       +
       +        if start < -len(aStr) {
       +                start = 0
       +        }
       +        if start > len(aStr) {
       +                return "", errors.New(fmt.Sprintf("start position out of bounds for %d-byte string", len(aStr)))
       +        }
       +
       +        var s, e int
       +        if start >= 0 && length >= 0 {
       +                s = start
       +                e = start + length
       +        } else if start < 0 && length >= 0 {
       +                s = len(aStr) + start - length + 1
       +                e = len(aStr) + start + 1
       +        } else if start >= 0 && length < 0 {
       +                s = start
       +                e = len(aStr) + length
       +        } else {
       +                s = len(aStr) + start
       +                e = len(aStr) + length
       +        }
       +
       +        if s > e {
       +                return "", errors.New(fmt.Sprintf("calculated start position greater than end position: %d > %d", s, e))
       +        }
       +        if e > len(aStr) {
       +                e = len(aStr)
       +        }
       +
       +        return aStr[s:e], nil
       +
       +}
       +
       +func Split(a interface{}, delimiter string) ([]string, error) {
       +        aStr, err := cast.ToStringE(a)
       +        if err != nil {
       +                return []string{}, err
       +        }
       +        return strings.Split(aStr, delimiter), nil
       +}
       +
       +func Intersect(l1, l2 interface{}) (interface{}, error) {
       +        if l1 == nil || l2 == nil {
       +                return make([]interface{}, 0), nil
       +        }
       +
       +        l1v := reflect.ValueOf(l1)
       +        l2v := reflect.ValueOf(l2)
       +
       +        switch l1v.Kind() {
       +        case reflect.Array, reflect.Slice:
       +                switch l2v.Kind() {
       +                case reflect.Array, reflect.Slice:
       +                        r := reflect.MakeSlice(l1v.Type(), 0, 0)
       +                        for i := 0; i < l1v.Len(); i++ {
       +                                l1vv := l1v.Index(i)
       +                                for j := 0; j < l2v.Len(); j++ {
       +                                        l2vv := l2v.Index(j)
       +                                        switch l1vv.Kind() {
       +                                        case reflect.String:
       +                                                if l1vv.Type() == l2vv.Type() && l1vv.String() == l2vv.String() && !In(r, l2vv) {
       +                                                        r = reflect.Append(r, l2vv)
       +                                                }
       +                                        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                                                switch l2vv.Kind() {
       +                                                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                                                        if l1vv.Int() == l2vv.Int() && !In(r, l2vv) {
       +                                                                r = reflect.Append(r, l2vv)
       +                                                        }
       +                                                }
       +                                        case reflect.Float32, reflect.Float64:
       +                                                switch l2vv.Kind() {
       +                                                case reflect.Float32, reflect.Float64:
       +                                                        if l1vv.Float() == l2vv.Float() && !In(r, l2vv) {
       +                                                                r = reflect.Append(r, l2vv)
       +                                                        }
       +                                                }
       +                                        }
       +                                }
       +                        }
       +                        return r.Interface(), nil
       +                default:
       +                        return nil, errors.New("can't iterate over " + reflect.ValueOf(l2).Type().String())
       +                }
       +        default:
       +                return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
       +        }
       +}
       +
       +func In(l interface{}, v interface{}) bool {
       +        lv := reflect.ValueOf(l)
       +        vv := reflect.ValueOf(v)
       +
       +        switch lv.Kind() {
       +        case reflect.Array, reflect.Slice:
       +                for i := 0; i < lv.Len(); i++ {
       +                        lvv := lv.Index(i)
       +                        switch lvv.Kind() {
       +                        case reflect.String:
       +                                if vv.Type() == lvv.Type() && vv.String() == lvv.String() {
       +                                        return true
       +                                }
       +                        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                                switch vv.Kind() {
       +                                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                                        if vv.Int() == lvv.Int() {
       +                                                return true
       +                                        }
       +                                }
       +                        case reflect.Float32, reflect.Float64:
       +                                switch vv.Kind() {
       +                                case reflect.Float32, reflect.Float64:
       +                                        if vv.Float() == lvv.Float() {
       +                                                return true
       +                                        }
       +                                }
       +                        }
       +                }
       +        case reflect.String:
       +                if vv.Type() == lv.Type() && strings.Contains(lv.String(), vv.String()) {
       +                        return true
       +                }
       +        }
       +        return false
       +}
       +
       +// indirect is taken from 'text/template/exec.go'
       +func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
       +        for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
       +                if v.IsNil() {
       +                        return v, true
       +                }
       +                if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
       +                        break
       +                }
       +        }
       +        return v, false
       +}
       +
       +// First is exposed to templates, to iterate over the first N items in a
       +// rangeable list.
       +func First(limit interface{}, seq interface{}) (interface{}, error) {
       +
       +        if limit == nil || seq == nil {
       +                return nil, errors.New("both limit and seq must be provided")
       +        }
       +
       +        limitv, err := cast.ToIntE(limit)
       +
       +        if err != nil {
       +                return nil, err
       +        }
       +
       +        if limitv < 1 {
       +                return nil, errors.New("can't return negative/empty count of items from sequence")
       +        }
       +
       +        seqv := reflect.ValueOf(seq)
       +        seqv, isNil := indirect(seqv)
       +        if isNil {
       +                return nil, errors.New("can't iterate over a nil value")
       +        }
       +
       +        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 limitv > seqv.Len() {
       +                limitv = seqv.Len()
       +        }
       +        return seqv.Slice(0, limitv).Interface(), nil
       +}
       +
       +var (
       +        zero      reflect.Value
       +        errorType = reflect.TypeOf((*error)(nil)).Elem()
       +)
       +
       +func evaluateSubElem(obj reflect.Value, elemName string) (reflect.Value, error) {
       +        if !obj.IsValid() {
       +                return zero, errors.New("can't evaluate an invalid value")
       +        }
       +        typ := obj.Type()
       +        obj, isNil := indirect(obj)
       +
       +        // first, check whether obj has a method. In this case, obj is
       +        // an interface, a struct or its pointer. If obj is a struct,
       +        // to check all T and *T method, use obj pointer type Value
       +        objPtr := obj
       +        if objPtr.Kind() != reflect.Interface && objPtr.CanAddr() {
       +                objPtr = objPtr.Addr()
       +        }
       +        mt, ok := objPtr.Type().MethodByName(elemName)
       +        if ok {
       +                if mt.PkgPath != "" {
       +                        return zero, fmt.Errorf("%s is an unexported method of type %s", elemName, typ)
       +                }
       +                // struct pointer has one receiver argument and interface doesn't have an argument
       +                if mt.Type.NumIn() > 1 || mt.Type.NumOut() == 0 || mt.Type.NumOut() > 2 {
       +                        return zero, fmt.Errorf("%s is a method of type %s but doesn't satisfy requirements", elemName, typ)
       +                }
       +                if mt.Type.NumOut() == 1 && mt.Type.Out(0).Implements(errorType) {
       +                        return zero, fmt.Errorf("%s is a method of type %s but doesn't satisfy requirements", elemName, typ)
       +                }
       +                if mt.Type.NumOut() == 2 && !mt.Type.Out(1).Implements(errorType) {
       +                        return zero, fmt.Errorf("%s is a method of type %s but doesn't satisfy requirements", elemName, typ)
       +                }
       +                res := objPtr.Method(mt.Index).Call([]reflect.Value{})
       +                if len(res) == 2 && !res[1].IsNil() {
       +                        return zero, fmt.Errorf("error at calling a method %s of type %s: %s", elemName, typ, res[1].Interface().(error))
       +                }
       +                return res[0], nil
       +        }
       +
       +        // elemName isn't a method so next start to check whether it is
       +        // a struct field or a map value. In both cases, it mustn't be
       +        // a nil value
       +        if isNil {
       +                return zero, fmt.Errorf("can't evaluate a nil pointer of type %s by a struct field or map key name %s", typ, elemName)
       +        }
       +        switch obj.Kind() {
       +        case reflect.Struct:
       +                ft, ok := obj.Type().FieldByName(elemName)
       +                if ok {
       +                        if ft.PkgPath != "" {
       +                                return zero, fmt.Errorf("%s is an unexported field of struct type %s", elemName, typ)
       +                        }
       +                        return obj.FieldByIndex(ft.Index), nil
       +                }
       +                return zero, fmt.Errorf("%s isn't a field of struct type %s", elemName, typ)
       +        case reflect.Map:
       +                kv := reflect.ValueOf(elemName)
       +                if kv.Type().AssignableTo(obj.Type().Key()) {
       +                        return obj.MapIndex(kv), nil
       +                }
       +                return zero, fmt.Errorf("%s isn't a key of map type %s", elemName, typ)
       +        }
       +        return zero, fmt.Errorf("%s is neither a struct field, a method nor a map element of type %s", elemName, typ)
       +}
       +
       +func checkCondition(v, mv reflect.Value, op string) (bool, error) {
       +        if !v.IsValid() || !mv.IsValid() {
       +                return false, nil
       +        }
       +
       +        var isNil bool
       +        v, isNil = indirect(v)
       +        if isNil {
       +                return false, nil
       +        }
       +        mv, isNil = indirect(mv)
       +        if isNil {
       +                return false, nil
       +        }
       +
       +        var ivp, imvp *int64
       +        var svp, smvp *string
       +        var ima []int64
       +        var sma []string
       +        if mv.Type() == v.Type() {
       +                switch v.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        iv := v.Int()
       +                        ivp = &iv
       +                        imv := mv.Int()
       +                        imvp = &imv
       +                case reflect.String:
       +                        sv := v.String()
       +                        svp = &sv
       +                        smv := mv.String()
       +                        smvp = &smv
       +                }
       +        } else {
       +                if mv.Kind() != reflect.Array && mv.Kind() != reflect.Slice {
       +                        return false, nil
       +                }
       +                if mv.Type().Elem() != v.Type() {
       +                        return false, nil
       +                }
       +                switch v.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        iv := v.Int()
       +                        ivp = &iv
       +                        for i := 0; i < mv.Len(); i++ {
       +                                ima = append(ima, mv.Index(i).Int())
       +                        }
       +                case reflect.String:
       +                        sv := v.String()
       +                        svp = &sv
       +                        for i := 0; i < mv.Len(); i++ {
       +                                sma = append(sma, mv.Index(i).String())
       +                        }
       +                }
       +        }
       +
       +        switch op {
       +        case "", "=", "==", "eq":
       +                if ivp != nil && imvp != nil {
       +                        return *ivp == *imvp, nil
       +                } else if svp != nil && smvp != nil {
       +                        return *svp == *smvp, nil
       +                }
       +        case "!=", "<>", "ne":
       +                if ivp != nil && imvp != nil {
       +                        return *ivp != *imvp, nil
       +                } else if svp != nil && smvp != nil {
       +                        return *svp != *smvp, nil
       +                }
       +        case ">=", "ge":
       +                if ivp != nil && imvp != nil {
       +                        return *ivp >= *imvp, nil
       +                } else if svp != nil && smvp != nil {
       +                        return *svp >= *smvp, nil
       +                }
       +        case ">", "gt":
       +                if ivp != nil && imvp != nil {
       +                        return *ivp > *imvp, nil
       +                } else if svp != nil && smvp != nil {
       +                        return *svp > *smvp, nil
       +                }
       +        case "<=", "le":
       +                if ivp != nil && imvp != nil {
       +                        return *ivp <= *imvp, nil
       +                } else if svp != nil && smvp != nil {
       +                        return *svp <= *smvp, nil
       +                }
       +        case "<", "lt":
       +                if ivp != nil && imvp != nil {
       +                        return *ivp < *imvp, nil
       +                } else if svp != nil && smvp != nil {
       +                        return *svp < *smvp, nil
       +                }
       +        case "in", "not in":
       +                var r bool
       +                if ivp != nil && len(ima) > 0 {
       +                        r = In(ima, *ivp)
       +                } else if svp != nil {
       +                        if len(sma) > 0 {
       +                                r = In(sma, *svp)
       +                        } else if smvp != nil {
       +                                r = In(*smvp, *svp)
       +                        }
       +                } else {
       +                        return false, nil
       +                }
       +                if op == "not in" {
       +                        return !r, nil
       +                } else {
       +                        return r, nil
       +                }
       +        default:
       +                return false, errors.New("no such an operator")
       +        }
       +        return false, nil
       +}
       +
       +func Where(seq, key interface{}, args ...interface{}) (r interface{}, err error) {
       +        seqv := reflect.ValueOf(seq)
       +        kv := reflect.ValueOf(key)
       +
       +        var mv reflect.Value
       +        var op string
       +        switch len(args) {
       +        case 1:
       +                mv = reflect.ValueOf(args[0])
       +        case 2:
       +                var ok bool
       +                if op, ok = args[0].(string); !ok {
       +                        return nil, errors.New("operator argument must be string type")
       +                }
       +                op = strings.TrimSpace(strings.ToLower(op))
       +                mv = reflect.ValueOf(args[1])
       +        default:
       +                return nil, errors.New("can't evaluate the array by no match argument or more than or equal to two arguments")
       +        }
       +
       +        seqv, isNil := indirect(seqv)
       +        if isNil {
       +                return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(seq).Type().String())
       +        }
       +
       +        var path []string
       +        if kv.Kind() == reflect.String {
       +                path = strings.Split(strings.Trim(kv.String(), "."), ".")
       +        }
       +
       +        switch seqv.Kind() {
       +        case reflect.Array, reflect.Slice:
       +                rv := reflect.MakeSlice(seqv.Type(), 0, 0)
       +                for i := 0; i < seqv.Len(); i++ {
       +                        var vvv reflect.Value
       +                        rvv := seqv.Index(i)
       +                        if kv.Kind() == reflect.String {
       +                                vvv = rvv
       +                                for _, elemName := range path {
       +                                        vvv, err = evaluateSubElem(vvv, elemName)
       +                                        if err != nil {
       +                                                return nil, err
       +                                        }
       +                                }
       +                        } else {
       +                                vv, _ := indirect(rvv)
       +                                if vv.Kind() == reflect.Map && kv.Type().AssignableTo(vv.Type().Key()) {
       +                                        vvv = vv.MapIndex(kv)
       +                                }
       +                        }
       +                        if ok, err := checkCondition(vvv, mv, op); ok {
       +                                rv = reflect.Append(rv, rvv)
       +                        } else if err != nil {
       +                                return nil, err
       +                        }
       +                }
       +                return rv.Interface(), nil
       +        default:
       +                return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
       +        }
       +}
       +
       +// Apply, given a map, array, or slice, returns a new slice with the function fname applied over it.
       +func Apply(seq interface{}, fname string, args ...interface{}) (interface{}, error) {
       +        if seq == nil {
       +                return make([]interface{}, 0), nil
       +        }
       +
       +        if fname == "apply" {
       +                return nil, errors.New("can't apply myself (no turtles allowed)")
       +        }
       +
       +        seqv := reflect.ValueOf(seq)
       +        seqv, isNil := indirect(seqv)
       +        if isNil {
       +                return nil, errors.New("can't iterate over a nil value")
       +        }
       +
       +        fn, found := funcMap[fname]
       +        if !found {
       +                return nil, errors.New("can't find function " + fname)
       +        }
       +
       +        fnv := reflect.ValueOf(fn)
       +
       +        switch seqv.Kind() {
       +        case reflect.Array, reflect.Slice:
       +                r := make([]interface{}, seqv.Len())
       +                for i := 0; i < seqv.Len(); i++ {
       +                        vv := seqv.Index(i)
       +
       +                        vvv, err := applyFnToThis(fnv, vv, args...)
       +
       +                        if err != nil {
       +                                return nil, err
       +                        }
       +
       +                        r[i] = vvv.Interface()
       +                }
       +
       +                return r, nil
       +        default:
       +                return nil, errors.New("can't apply over " + reflect.ValueOf(seq).Type().String())
       +        }
       +}
       +
       +func applyFnToThis(fn, this reflect.Value, args ...interface{}) (reflect.Value, error) {
       +        n := make([]reflect.Value, len(args))
       +        for i, arg := range args {
       +                if arg == "." {
       +                        n[i] = this
       +                } else {
       +                        n[i] = reflect.ValueOf(arg)
       +                }
       +        }
       +
       +        res := fn.Call(n)
       +
       +        if len(res) == 1 || res[1].IsNil() {
       +                return res[0], nil
       +        } else {
       +                return reflect.ValueOf(nil), res[1].Interface().(error)
       +        }
       +}
       +
       +func Delimit(seq, delimiter interface{}, last ...interface{}) (template.HTML, error) {
       +        d, err := cast.ToStringE(delimiter)
       +        if err != nil {
       +                return "", err
       +        }
       +
       +        var dLast *string
       +        for _, l := range last {
       +                dStr, err := cast.ToStringE(l)
       +                if err != nil {
       +                        dLast = nil
       +                }
       +                dLast = &dStr
       +                break
       +        }
       +
       +        seqv := reflect.ValueOf(seq)
       +        seqv, isNil := indirect(seqv)
       +        if isNil {
       +                return "", errors.New("can't iterate over a nil value")
       +        }
       +
       +        var str string
       +        switch seqv.Kind() {
       +        case reflect.Map:
       +                sortSeq, err := Sort(seq)
       +                if err != nil {
       +                        return "", err
       +                }
       +                seqv = reflect.ValueOf(sortSeq)
       +                fallthrough
       +        case reflect.Array, reflect.Slice, reflect.String:
       +                for i := 0; i < seqv.Len(); i++ {
       +                        val := seqv.Index(i).Interface()
       +                        valStr, err := cast.ToStringE(val)
       +                        if err != nil {
       +                                continue
       +                        }
       +                        switch {
       +                        case i == seqv.Len()-2 && dLast != nil:
       +                                str += valStr + *dLast
       +                        case i == seqv.Len()-1:
       +                                str += valStr
       +                        default:
       +                                str += valStr + d
       +                        }
       +                }
       +
       +        default:
       +                return "", errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
       +        }
       +
       +        return template.HTML(str), nil
       +}
       +
       +func Sort(seq interface{}, args ...interface{}) ([]interface{}, error) {
       +        seqv := reflect.ValueOf(seq)
       +        seqv, isNil := indirect(seqv)
       +        if isNil {
       +                return nil, errors.New("can't iterate over a nil value")
       +        }
       +
       +        // Create a list of pairs that will be used to do the sort
       +        p := pairList{SortAsc: true}
       +        p.Pairs = make([]pair, seqv.Len())
       +
       +        for i, l := range args {
       +                dStr, err := cast.ToStringE(l)
       +                switch {
       +                case i == 0 && err != nil:
       +                        p.SortByField = ""
       +                case i == 0 && err == nil:
       +                        p.SortByField = dStr
       +                case i == 1 && err == nil && dStr == "desc":
       +                        p.SortAsc = false
       +                case i == 1:
       +                        p.SortAsc = true
       +                }
       +        }
       +
       +        var sorted []interface{}
       +        switch seqv.Kind() {
       +        case reflect.Array, reflect.Slice:
       +                for i := 0; i < seqv.Len(); i++ {
       +                        p.Pairs[i].Key = reflect.ValueOf(i)
       +                        p.Pairs[i].Value = seqv.Index(i)
       +                }
       +                if p.SortByField == "" {
       +                        p.SortByField = "value"
       +                }
       +
       +        case reflect.Map:
       +                keys := seqv.MapKeys()
       +                for i := 0; i < seqv.Len(); i++ {
       +                        p.Pairs[i].Key = keys[i]
       +                        p.Pairs[i].Value = seqv.MapIndex(keys[i])
       +                }
       +
       +        default:
       +                return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String())
       +        }
       +        sorted = p.sort()
       +        return sorted, nil
       +}
       +
       +// Credit for pair sorting method goes to Andrew Gerrand
       +// https://groups.google.com/forum/#!topic/golang-nuts/FT7cjmcL7gw
       +// A data structure to hold a key/value pair.
       +type pair struct {
       +        Key   reflect.Value
       +        Value reflect.Value
       +}
       +
       +// A slice of pairs that implements sort.Interface to sort by Value.
       +type pairList struct {
       +        Pairs       []pair
       +        SortByField string
       +        SortAsc     bool
       +}
       +
       +func (p pairList) Swap(i, j int) { p.Pairs[i], p.Pairs[j] = p.Pairs[j], p.Pairs[i] }
       +func (p pairList) Len() int      { return len(p.Pairs) }
       +func (p pairList) Less(i, j int) bool {
       +        var truth bool
       +        switch {
       +        case p.SortByField == "value":
       +                iVal := p.Pairs[i].Value
       +                jVal := p.Pairs[j].Value
       +                truth = Lt(iVal.Interface(), jVal.Interface())
       +
       +        case p.SortByField != "":
       +                if p.Pairs[i].Value.FieldByName(p.SortByField).IsValid() {
       +                        iVal := p.Pairs[i].Value.FieldByName(p.SortByField)
       +                        jVal := p.Pairs[j].Value.FieldByName(p.SortByField)
       +                        truth = Lt(iVal.Interface(), jVal.Interface())
       +                }
       +        default:
       +                iVal := p.Pairs[i].Key
       +                jVal := p.Pairs[j].Key
       +                truth = Lt(iVal.Interface(), jVal.Interface())
       +        }
       +        return truth
       +}
       +
       +// sorts a pairList and returns a slice of sorted values
       +func (p pairList) sort() []interface{} {
       +        if p.SortAsc {
       +                sort.Sort(p)
       +        } else {
       +                sort.Sort(sort.Reverse(p))
       +        }
       +        sorted := make([]interface{}, len(p.Pairs))
       +        for i, v := range p.Pairs {
       +                sorted[i] = v.Value.Interface()
       +        }
       +
       +        return sorted
       +}
       +
       +func IsSet(a interface{}, key interface{}) bool {
       +        av := reflect.ValueOf(a)
       +        kv := reflect.ValueOf(key)
       +
       +        switch av.Kind() {
       +        case reflect.Array, reflect.Chan, reflect.Slice:
       +                if int64(av.Len()) > kv.Int() {
       +                        return true
       +                }
       +        case reflect.Map:
       +                if kv.Type() == av.Type().Key() {
       +                        return av.MapIndex(kv).IsValid()
       +                }
       +        }
       +
       +        return false
       +}
       +
       +func ReturnWhenSet(a, k interface{}) interface{} {
       +        av, isNil := indirect(reflect.ValueOf(a))
       +        if isNil {
       +                return ""
       +        }
       +
       +        var avv reflect.Value
       +        switch av.Kind() {
       +        case reflect.Array, reflect.Slice:
       +                index, ok := k.(int)
       +                if ok && av.Len() > index {
       +                        avv = av.Index(index)
       +                }
       +        case reflect.Map:
       +                kv := reflect.ValueOf(k)
       +                if kv.Type().AssignableTo(av.Type().Key()) {
       +                        avv = av.MapIndex(kv)
       +                }
       +        }
       +
       +        if avv.IsValid() {
       +                switch avv.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        return avv.Int()
       +                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       +                        return avv.Uint()
       +                case reflect.Float32, reflect.Float64:
       +                        return avv.Float()
       +                case reflect.String:
       +                        return avv.String()
       +                }
       +        }
       +
       +        return ""
       +}
       +
       +func Highlight(in interface{}, lang string) template.HTML {
       +        var str string
       +        av := reflect.ValueOf(in)
       +        switch av.Kind() {
       +        case reflect.String:
       +                str = av.String()
       +        }
       +
       +        return template.HTML(helpers.Highlight(html.UnescapeString(str), lang))
       +}
       +
       +var markdownTrimPrefix = []byte("<p>")
       +var markdownTrimSuffix = []byte("</p>\n")
       +
       +func Markdownify(text string) template.HTML {
       +        m := helpers.RenderBytes(&helpers.RenderingContext{Content: []byte(text), PageFmt: "markdown"})
       +        m = bytes.TrimPrefix(m, markdownTrimPrefix)
       +        m = bytes.TrimSuffix(m, markdownTrimSuffix)
       +        return template.HTML(m)
       +}
       +
       +func refPage(page interface{}, ref, methodName string) template.HTML {
       +        value := reflect.ValueOf(page)
       +
       +        method := value.MethodByName(methodName)
       +
       +        if method.IsValid() && method.Type().NumIn() == 1 && method.Type().NumOut() == 2 {
       +                result := method.Call([]reflect.Value{reflect.ValueOf(ref)})
       +
       +                url, err := result[0], result[1]
       +
       +                if !err.IsNil() {
       +                        jww.ERROR.Printf("%s", err.Interface())
       +                        return template.HTML(fmt.Sprintf("%s", err.Interface()))
       +                }
       +
       +                if url.String() == "" {
       +                        jww.ERROR.Printf("ref %s could not be found\n", ref)
       +                        return template.HTML(ref)
       +                }
       +
       +                return template.HTML(url.String())
       +        }
       +
       +        jww.ERROR.Printf("Can only create references from Page and Node objects.")
       +        return template.HTML(ref)
       +}
       +
       +func Ref(page interface{}, ref string) template.HTML {
       +        return refPage(page, ref, "Ref")
       +}
       +
       +func RelRef(page interface{}, ref string) template.HTML {
       +        return refPage(page, ref, "RelRef")
       +}
       +
       +func Chomp(text interface{}) (string, error) {
       +        s, err := cast.ToStringE(text)
       +        if err != nil {
       +                return "", err
       +        }
       +
       +        return strings.TrimRight(s, "\r\n"), nil
       +}
       +
       +// Trim leading/trailing characters defined by b from a
       +func Trim(a interface{}, b string) (string, error) {
       +        aStr, err := cast.ToStringE(a)
       +        if err != nil {
       +                return "", err
       +        }
       +        return strings.Trim(aStr, b), nil
       +}
       +
       +// Replace all occurences of b with c in a
       +func Replace(a, b, c interface{}) (string, error) {
       +        aStr, err := cast.ToStringE(a)
       +        if err != nil {
       +                return "", err
       +        }
       +        bStr, err := cast.ToStringE(b)
       +        if err != nil {
       +                return "", err
       +        }
       +        cStr, err := cast.ToStringE(c)
       +        if err != nil {
       +                return "", err
       +        }
       +        return strings.Replace(aStr, bStr, cStr, -1), nil
       +}
       +
       +// DateFormat converts the textual representation of the datetime string into
       +// the other form or returns it of the time.Time value. These are formatted
       +// with the layout string
       +func DateFormat(layout string, v interface{}) (string, error) {
       +        t, err := cast.ToTimeE(v)
       +        if err != nil {
       +                return "", err
       +        }
       +        return t.Format(layout), nil
       +}
       +
       +func SafeHTML(text string) template.HTML {
       +        return template.HTML(text)
       +}
       +
       +// "safeHTMLAttr" is currently disabled, pending further discussion
       +// on its use case.  2015-01-19
       +func SafeHTMLAttr(text string) template.HTMLAttr {
       +        return template.HTMLAttr(text)
       +}
       +
       +func SafeCSS(text string) template.CSS {
       +        return template.CSS(text)
       +}
       +
       +func SafeURL(text string) template.URL {
       +        return template.URL(text)
       +}
       +
       +func doArithmetic(a, b interface{}, op rune) (interface{}, error) {
       +        av := reflect.ValueOf(a)
       +        bv := reflect.ValueOf(b)
       +        var ai, bi int64
       +        var af, bf float64
       +        var au, bu uint64
       +        switch av.Kind() {
       +        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                ai = av.Int()
       +                switch bv.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        bi = bv.Int()
       +                case reflect.Float32, reflect.Float64:
       +                        af = float64(ai) // may overflow
       +                        ai = 0
       +                        bf = bv.Float()
       +                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       +                        bu = bv.Uint()
       +                        if ai >= 0 {
       +                                au = uint64(ai)
       +                                ai = 0
       +                        } else {
       +                                bi = int64(bu) // may overflow
       +                                bu = 0
       +                        }
       +                default:
       +                        return nil, errors.New("Can't apply the operator to the values")
       +                }
       +        case reflect.Float32, reflect.Float64:
       +                af = av.Float()
       +                switch bv.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        bf = float64(bv.Int()) // may overflow
       +                case reflect.Float32, reflect.Float64:
       +                        bf = bv.Float()
       +                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       +                        bf = float64(bv.Uint()) // may overflow
       +                default:
       +                        return nil, errors.New("Can't apply the operator to the values")
       +                }
       +        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       +                au = av.Uint()
       +                switch bv.Kind() {
       +                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                        bi = bv.Int()
       +                        if bi >= 0 {
       +                                bu = uint64(bi)
       +                                bi = 0
       +                        } else {
       +                                ai = int64(au) // may overflow
       +                                au = 0
       +                        }
       +                case reflect.Float32, reflect.Float64:
       +                        af = float64(au) // may overflow
       +                        au = 0
       +                        bf = bv.Float()
       +                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
       +                        bu = bv.Uint()
       +                default:
       +                        return nil, errors.New("Can't apply the operator to the values")
       +                }
       +        case reflect.String:
       +                as := av.String()
       +                if bv.Kind() == reflect.String && op == '+' {
       +                        bs := bv.String()
       +                        return as + bs, nil
       +                } else {
       +                        return nil, errors.New("Can't apply the operator to the values")
       +                }
       +        default:
       +                return nil, errors.New("Can't apply the operator to the values")
       +        }
       +
       +        switch op {
       +        case '+':
       +                if ai != 0 || bi != 0 {
       +                        return ai + bi, nil
       +                } else if af != 0 || bf != 0 {
       +                        return af + bf, nil
       +                } else if au != 0 || bu != 0 {
       +                        return au + bu, nil
       +                } else {
       +                        return 0, nil
       +                }
       +        case '-':
       +                if ai != 0 || bi != 0 {
       +                        return ai - bi, nil
       +                } else if af != 0 || bf != 0 {
       +                        return af - bf, nil
       +                } else if au != 0 || bu != 0 {
       +                        return au - bu, nil
       +                } else {
       +                        return 0, nil
       +                }
       +        case '*':
       +                if ai != 0 || bi != 0 {
       +                        return ai * bi, nil
       +                } else if af != 0 || bf != 0 {
       +                        return af * bf, nil
       +                } else if au != 0 || bu != 0 {
       +                        return au * bu, nil
       +                } else {
       +                        return 0, nil
       +                }
       +        case '/':
       +                if bi != 0 {
       +                        return ai / bi, nil
       +                } else if bf != 0 {
       +                        return af / bf, nil
       +                } else if bu != 0 {
       +                        return au / bu, nil
       +                } else {
       +                        return nil, errors.New("Can't divide the value by 0")
       +                }
       +        default:
       +                return nil, errors.New("There is no such an operation")
       +        }
       +}
       +
       +func Mod(a, b interface{}) (int64, error) {
       +        av := reflect.ValueOf(a)
       +        bv := reflect.ValueOf(b)
       +        var ai, bi int64
       +
       +        switch av.Kind() {
       +        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                ai = av.Int()
       +        default:
       +                return 0, errors.New("Modulo operator can't be used with non integer value")
       +        }
       +
       +        switch bv.Kind() {
       +        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
       +                bi = bv.Int()
       +        default:
       +                return 0, errors.New("Modulo operator can't be used with non integer value")
       +        }
       +
       +        if bi == 0 {
       +                return 0, errors.New("The number can't be divided by zero at modulo operation")
       +        }
       +
       +        return ai % bi, nil
       +}
       +
       +func ModBool(a, b interface{}) (bool, error) {
       +        res, err := Mod(a, b)
       +        if err != nil {
       +                return false, err
       +        }
       +        return res == int64(0), nil
       +}
       +
       +func init() {
       +        funcMap = template.FuncMap{
       +                "urlize":      helpers.URLize,
       +                "sanitizeURL": helpers.SanitizeURL,
       +                "sanitizeurl": helpers.SanitizeURL,
       +                "eq":          Eq,
       +                "ne":          Ne,
       +                "gt":          Gt,
       +                "ge":          Ge,
       +                "lt":          Lt,
       +                "le":          Le,
       +                "in":          In,
       +                "slicestr":    Slicestr,
       +                "substr":      Substr,
       +                "split":       Split,
       +                "intersect":   Intersect,
       +                "isSet":       IsSet,
       +                "isset":       IsSet,
       +                "echoParam":   ReturnWhenSet,
       +                "safeHTML":    SafeHTML,
       +                "safeCSS":     SafeCSS,
       +                "safeURL":     SafeURL,
       +                "markdownify": Markdownify,
       +                "first":       First,
       +                "where":       Where,
       +                "delimit":     Delimit,
       +                "sort":        Sort,
       +                "highlight":   Highlight,
       +                "add":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
       +                "sub":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
       +                "div":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
       +                "mod":         Mod,
       +                "mul":         func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
       +                "modBool":     ModBool,
       +                "lower":       func(a string) string { return strings.ToLower(a) },
       +                "upper":       func(a string) string { return strings.ToUpper(a) },
       +                "title":       func(a string) string { return strings.Title(a) },
       +                "partial":     Partial,
       +                "ref":         Ref,
       +                "relref":      RelRef,
       +                "apply":       Apply,
       +                "chomp":       Chomp,
       +                "replace":     Replace,
       +                "trim":        Trim,
       +                "dateFormat":  DateFormat,
       +                "getJSON":     GetJSON,
       +                "getCSV":      GetCSV,
       +                "seq":         helpers.Seq,
       +                "getenv":      func(varName string) string { return os.Getenv(varName) },
       +
       +                // "getJson" is deprecated. Will be removed in 0.15.
       +                "getJson": func(urlParts ...string) interface{} {
       +                        helpers.Deprecated("Template", "getJson", "getJSON")
       +                        return GetJSON(urlParts...)
       +                },
       +                // "getJson" is deprecated. Will be removed in 0.15.
       +                "getCsv": func(sep string, urlParts ...string) [][]string {
       +                        helpers.Deprecated("Template", "getCsv", "getCSV")
       +                        return GetCSV(sep, urlParts...)
       +                },
       +                // "safeHtml" is deprecated. Will be removed in 0.15.
       +                "safeHtml": func(text string) template.HTML {
       +                        helpers.Deprecated("Template", "safeHtml", "safeHTML")
       +                        return SafeHTML(text)
       +                },
       +                // "safeCss" is deprecated. Will be removed in 0.15.
       +                "safeCss": func(text string) template.CSS {
       +                        helpers.Deprecated("Template", "safeCss", "safeCSS")
       +                        return SafeCSS(text)
       +                },
       +                // "safeUrl" is deprecated. Will be removed in 0.15.
       +                "safeUrl": func(text string) template.URL {
       +                        helpers.Deprecated("Template", "safeUrl", "safeURL")
       +                        return SafeURL(text)
       +                },
       +        }
       +
       +}
 (DIR) diff --git a/tpl/template_test.go b/tpl/template_funcs_test.go
 (DIR) diff --git a/tpl/template_test.go b/tpl/template_test.go
       @@ -1,1222 +1,3 @@
        package tpl
        
       -import (
       -        "bytes"
       -        "errors"
       -        "fmt"
       -        "github.com/stretchr/testify/assert"
       -        "html/template"
       -        "path"
       -        "reflect"
       -        "runtime"
       -        "testing"
       -        "time"
       -)
       -
       -type tstNoStringer struct {
       -}
       -
       -type tstCompareType int
       -
       -const (
       -        tstEq tstCompareType = iota
       -        tstNe
       -        tstGt
       -        tstGe
       -        tstLt
       -        tstLe
       -)
       -
       -func tstIsEq(tp tstCompareType) bool {
       -        return tp == tstEq || tp == tstGe || tp == tstLe
       -}
       -
       -func tstIsGt(tp tstCompareType) bool {
       -        return tp == tstGt || tp == tstGe
       -}
       -
       -func tstIsLt(tp tstCompareType) bool {
       -        return tp == tstLt || tp == tstLe
       -}
       -
       -func TestCompare(t *testing.T) {
       -        for _, this := range []struct {
       -                tstCompareType
       -                funcUnderTest func(a, b interface{}) bool
       -        }{
       -                {tstGt, Gt},
       -                {tstLt, Lt},
       -                {tstGe, Ge},
       -                {tstLe, Le},
       -                {tstEq, Eq},
       -                {tstNe, Ne},
       -        } {
       -                doTestCompare(t, this.tstCompareType, this.funcUnderTest)
       -        }
       -
       -}
       -
       -func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b interface{}) bool) {
       -        for i, this := range []struct {
       -                left            interface{}
       -                right           interface{}
       -                expectIndicator int
       -        }{
       -                {5, 8, -1},
       -                {8, 5, 1},
       -                {5, 5, 0},
       -                {int(5), int64(5), 0},
       -                {int32(5), int(5), 0},
       -                {int16(4), int(5), -1},
       -                {uint(15), uint64(15), 0},
       -                {-2, 1, -1},
       -                {2, -5, 1},
       -                {0.0, 1.23, -1},
       -                {1.1, 1.1, 0},
       -                {float32(1.0), float64(1.0), 0},
       -                {1.23, 0.0, 1},
       -                {"5", "5", 0},
       -                {"8", "5", 1},
       -                {"5", "0001", 1},
       -                {[]int{100, 99}, []int{1, 2, 3, 4}, -1},
       -        } {
       -                result := funcUnderTest(this.left, this.right)
       -                success := false
       -
       -                if this.expectIndicator == 0 {
       -                        if tstIsEq(tp) {
       -                                success = result
       -                        } else {
       -                                success = !result
       -                        }
       -                }
       -
       -                if this.expectIndicator < 0 {
       -                        success = result && (tstIsLt(tp) || tp == tstNe)
       -                        success = success || (!result && !tstIsLt(tp))
       -                }
       -
       -                if this.expectIndicator > 0 {
       -                        success = result && (tstIsGt(tp) || tp == tstNe)
       -                        success = success || (!result && (!tstIsGt(tp) || tp != tstNe))
       -                }
       -
       -                if !success {
       -                        t.Errorf("[%d][%s] %v compared to %v: %t", i, path.Base(runtime.FuncForPC(reflect.ValueOf(funcUnderTest).Pointer()).Name()), this.left, this.right, result)
       -                }
       -        }
       -}
       -
       -func TestArethmic(t *testing.T) {
       -        for i, this := range []struct {
       -                a      interface{}
       -                b      interface{}
       -                op     rune
       -                expect interface{}
       -        }{
       -                {1, 2, '+', int64(3)},
       -                {1, 2, '-', int64(-1)},
       -                {2, 2, '*', int64(4)},
       -                {4, 2, '/', int64(2)},
       -                {uint8(1), uint8(3), '+', uint64(4)},
       -                {uint8(3), uint8(2), '-', uint64(1)},
       -                {uint8(2), uint8(2), '*', uint64(4)},
       -                {uint16(4), uint8(2), '/', uint64(2)},
       -                {4, 2, '¤', false},
       -                {4, 0, '/', false},
       -        } {
       -                // TODO(bep): Take precision into account.
       -                result, err := doArithmetic(this.a, this.b, this.op)
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] doArethmic didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(result, this.expect) {
       -                                t.Errorf("[%d] doArethmic got %v (%T) but expected %v (%T)", i, result, result, this.expect, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestMod(t *testing.T) {
       -        for i, this := range []struct {
       -                a      interface{}
       -                b      interface{}
       -                expect interface{}
       -        }{
       -                {3, 2, int64(1)},
       -                {3, 1, int64(0)},
       -                {3, 0, false},
       -                {0, 3, int64(0)},
       -                {3.1, 2, false},
       -                {3, 2.1, false},
       -                {3.1, 2.1, false},
       -                {int8(3), int8(2), int64(1)},
       -                {int16(3), int16(2), int64(1)},
       -                {int32(3), int32(2), int64(1)},
       -                {int64(3), int64(2), int64(1)},
       -        } {
       -                result, err := Mod(this.a, this.b)
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] modulo didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(result, this.expect) {
       -                                t.Errorf("[%d] modulo got %v but expected %v", i, result, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestModBool(t *testing.T) {
       -        for i, this := range []struct {
       -                a      interface{}
       -                b      interface{}
       -                expect interface{}
       -        }{
       -                {3, 3, true},
       -                {3, 2, false},
       -                {3, 1, true},
       -                {3, 0, nil},
       -                {0, 3, true},
       -                {3.1, 2, nil},
       -                {3, 2.1, nil},
       -                {3.1, 2.1, nil},
       -                {int8(3), int8(3), true},
       -                {int8(3), int8(2), false},
       -                {int16(3), int16(3), true},
       -                {int16(3), int16(2), false},
       -                {int32(3), int32(3), true},
       -                {int32(3), int32(2), false},
       -                {int64(3), int64(3), true},
       -                {int64(3), int64(2), false},
       -        } {
       -                result, err := ModBool(this.a, this.b)
       -                if this.expect == nil {
       -                        if err == nil {
       -                                t.Errorf("[%d] modulo didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(result, this.expect) {
       -                                t.Errorf("[%d] modulo got %v but expected %v", i, result, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestFirst(t *testing.T) {
       -        for i, this := range []struct {
       -                count    interface{}
       -                sequence interface{}
       -                expect   interface{}
       -        }{
       -                {int(2), []string{"a", "b", "c"}, []string{"a", "b"}},
       -                {int32(3), []string{"a", "b"}, []string{"a", "b"}},
       -                {int64(2), []int{100, 200, 300}, []int{100, 200}},
       -                {100, []int{100, 200}, []int{100, 200}},
       -                {"1", []int{100, 200, 300}, []int{100}},
       -                {int64(-1), []int{100, 200, 300}, false},
       -                {"noint", []int{100, 200, 300}, false},
       -                {1, nil, false},
       -                {nil, []int{100}, false},
       -                {1, t, false},
       -        } {
       -                results, err := First(this.count, this.sequence)
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] First didn't return an expected error", i)
       -                        }
       -                } else {
       -                        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)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestIn(t *testing.T) {
       -        for i, this := range []struct {
       -                v1     interface{}
       -                v2     interface{}
       -                expect bool
       -        }{
       -                {[]string{"a", "b", "c"}, "b", true},
       -                {[]string{"a", "b", "c"}, "d", false},
       -                {[]string{"a", "12", "c"}, 12, false},
       -                {[]int{1, 2, 4}, 2, true},
       -                {[]int{1, 2, 4}, 3, false},
       -                {[]float64{1.23, 2.45, 4.67}, 1.23, true},
       -                {[]float64{1.234567, 2.45, 4.67}, 1.234568, false},
       -                {"this substring should be found", "substring", true},
       -                {"this substring should not be found", "subseastring", false},
       -        } {
       -                result := In(this.v1, this.v2)
       -
       -                if result != this.expect {
       -                        t.Errorf("[%d] Got %v but expected %v", i, result, this.expect)
       -                }
       -        }
       -}
       -
       -func TestSlicestr(t *testing.T) {
       -        for i, this := range []struct {
       -                v1     interface{}
       -                v2     []int
       -                expect interface{}
       -        }{
       -                {"abc", []int{1, 2}, "b"},
       -                {"abc", []int{1, 3}, "bc"},
       -                {"abc", []int{0, 1}, "a"},
       -                {"abcdef", []int{}, "abcdef"},
       -                {"abcdef", []int{0, 6}, "abcdef"},
       -                {"abcdef", []int{0, 2}, "ab"},
       -                {"abcdef", []int{2}, "cdef"},
       -                {123, []int{1, 3}, "23"},
       -                {123, []int{1, 2, 3}, false},
       -                {tstNoStringer{}, []int{0, 1}, false},
       -        } {
       -                result, err := Slicestr(this.v1, this.v2...)
       -
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] Slice didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(result, this.expect) {
       -                                t.Errorf("[%d] Got %s but expected %s", i, result, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestSubstr(t *testing.T) {
       -        for i, this := range []struct {
       -                v1     interface{}
       -                v2     int
       -                v3     int
       -                expect interface{}
       -        }{
       -                {"abc", 1, 2, "bc"},
       -                {"abc", 0, 1, "a"},
       -                {"abcdef", -1, 2, "ef"},
       -                {"abcdef", -3, 3, "bcd"},
       -                {"abcdef", 0, -1, "abcde"},
       -                {"abcdef", 2, -1, "cde"},
       -                {"abcdef", 4, -4, false},
       -                {"abcdef", 7, 1, false},
       -                {"abcdef", 1, 100, "bcdef"},
       -                {"abcdef", -100, 3, "abc"},
       -                {"abcdef", -3, -1, "de"},
       -                {123, 1, 3, "23"},
       -                {1.2e3, 0, 4, "1200"},
       -                {tstNoStringer{}, 0, 1, false},
       -        } {
       -                result, err := Substr(this.v1, this.v2, this.v3)
       -
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] Substr didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(result, this.expect) {
       -                                t.Errorf("[%d] Got %s but expected %s", i, result, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestSplit(t *testing.T) {
       -        for i, this := range []struct {
       -                v1     interface{}
       -                v2     string
       -                expect interface{}
       -        }{
       -                {"a, b", ", ", []string{"a", "b"}},
       -                {"a & b & c", " & ", []string{"a", "b", "c"}},
       -                {"http://exmaple.com", "http://", []string{"", "exmaple.com"}},
       -                {123, "2", []string{"1", "3"}},
       -                {tstNoStringer{}, ",", false},
       -        } {
       -                result, err := Split(this.v1, this.v2)
       -
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] Split didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(result, this.expect) {
       -                                t.Errorf("[%d] Got %s but expected %s", i, result, this.expect)
       -                        }
       -                }
       -        }
       -
       -}
       -
       -func TestIntersect(t *testing.T) {
       -        for i, this := range []struct {
       -                sequence1 interface{}
       -                sequence2 interface{}
       -                expect    interface{}
       -        }{
       -                {[]string{"a", "b", "c"}, []string{"a", "b"}, []string{"a", "b"}},
       -                {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{"a", "b"}},
       -                {[]string{"a", "b", "c"}, []string{"d", "e"}, []string{}},
       -                {[]string{}, []string{}, []string{}},
       -                {[]string{"a", "b"}, nil, make([]interface{}, 0)},
       -                {nil, []string{"a", "b"}, make([]interface{}, 0)},
       -                {nil, nil, make([]interface{}, 0)},
       -                {[]string{"1", "2"}, []int{1, 2}, []string{}},
       -                {[]int{1, 2}, []string{"1", "2"}, []int{}},
       -                {[]int{1, 2, 4}, []int{2, 4}, []int{2, 4}},
       -                {[]int{2, 4}, []int{1, 2, 4}, []int{2, 4}},
       -                {[]int{1, 2, 4}, []int{3, 6}, []int{}},
       -                {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4}},
       -        } {
       -                results, err := Intersect(this.sequence1, this.sequence2)
       -                if err != nil {
       -                        t.Errorf("[%d] failed: %s", i, err)
       -                        continue
       -                }
       -                if !reflect.DeepEqual(results, this.expect) {
       -                        t.Errorf("[%d] Got %v but expected %v", i, results, this.expect)
       -                }
       -        }
       -
       -        _, err1 := Intersect("not an array or slice", []string{"a"})
       -
       -        if err1 == nil {
       -                t.Error("Excpected error for non array as first arg")
       -        }
       -
       -        _, err2 := Intersect([]string{"a"}, "not an array or slice")
       -
       -        if err2 == nil {
       -                t.Error("Excpected error for non array as second arg")
       -        }
       -}
       -
       -func TestIsSet(t *testing.T) {
       -        aSlice := []interface{}{1, 2, 3, 5}
       -        aMap := map[string]interface{}{"a": 1, "b": 2}
       -
       -        assert.True(t, IsSet(aSlice, 2))
       -        assert.True(t, IsSet(aMap, "b"))
       -        assert.False(t, IsSet(aSlice, 22))
       -        assert.False(t, IsSet(aMap, "bc"))
       -}
       -
       -func (x *TstX) TstRp() string {
       -        return "r" + x.A
       -}
       -
       -func (x TstX) TstRv() string {
       -        return "r" + x.B
       -}
       -
       -func (x TstX) unexportedMethod() string {
       -        return x.unexported
       -}
       -
       -func (x TstX) MethodWithArg(s string) string {
       -        return s
       -}
       -
       -func (x TstX) MethodReturnNothing() {}
       -
       -func (x TstX) MethodReturnErrorOnly() error {
       -        return errors.New("something error occured")
       -}
       -
       -func (x TstX) MethodReturnTwoValues() (string, string) {
       -        return "foo", "bar"
       -}
       -
       -func (x TstX) MethodReturnValueWithError() (string, error) {
       -        return "", errors.New("something error occured")
       -}
       -
       -func (x TstX) String() string {
       -        return fmt.Sprintf("A: %s, B: %s", x.A, x.B)
       -}
       -
       -type TstX struct {
       -        A, B       string
       -        unexported string
       -}
       -
       -func TestEvaluateSubElem(t *testing.T) {
       -        tstx := TstX{A: "foo", B: "bar"}
       -        var inner struct {
       -                S fmt.Stringer
       -        }
       -        inner.S = tstx
       -        interfaceValue := reflect.ValueOf(&inner).Elem().Field(0)
       -
       -        for i, this := range []struct {
       -                value  reflect.Value
       -                key    string
       -                expect interface{}
       -        }{
       -                {reflect.ValueOf(tstx), "A", "foo"},
       -                {reflect.ValueOf(&tstx), "TstRp", "rfoo"},
       -                {reflect.ValueOf(tstx), "TstRv", "rbar"},
       -                //{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1, "foo"},
       -                {reflect.ValueOf(map[string]string{"key1": "foo", "key2": "bar"}), "key1", "foo"},
       -                {interfaceValue, "String", "A: foo, B: bar"},
       -                {reflect.Value{}, "foo", false},
       -                //{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1.2, false},
       -                {reflect.ValueOf(tstx), "unexported", false},
       -                {reflect.ValueOf(tstx), "unexportedMethod", false},
       -                {reflect.ValueOf(tstx), "MethodWithArg", false},
       -                {reflect.ValueOf(tstx), "MethodReturnNothing", false},
       -                {reflect.ValueOf(tstx), "MethodReturnErrorOnly", false},
       -                {reflect.ValueOf(tstx), "MethodReturnTwoValues", false},
       -                {reflect.ValueOf(tstx), "MethodReturnValueWithError", false},
       -                {reflect.ValueOf((*TstX)(nil)), "A", false},
       -                {reflect.ValueOf(tstx), "C", false},
       -                {reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), "1", false},
       -                {reflect.ValueOf([]string{"foo", "bar"}), "1", false},
       -        } {
       -                result, err := evaluateSubElem(this.value, this.key)
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] evaluateSubElem didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if result.Kind() != reflect.String || result.String() != this.expect {
       -                                t.Errorf("[%d] evaluateSubElem with %v got %v but expected %v", i, this.key, result, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestCheckCondition(t *testing.T) {
       -        type expect struct {
       -                result  bool
       -                isError bool
       -        }
       -
       -        for i, this := range []struct {
       -                value reflect.Value
       -                match reflect.Value
       -                op    string
       -                expect
       -        }{
       -                {reflect.ValueOf(123), reflect.ValueOf(123), "", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf("foo"), "", expect{true, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
       -                {reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
       -                {reflect.ValueOf(456), reflect.ValueOf(123), ">", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">", expect{true, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf(456), "<=", expect{true, false}},
       -                {reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<=", expect{true, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf(456), "<", expect{true, false}},
       -                {reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<", expect{true, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf([]int{123, 45, 678}), "in", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf([]string{"foo", "bar", "baz"}), "in", expect{true, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf([]int{45, 678}), "not in", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf([]string{"bar", "baz"}), "not in", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf("bar-foo-baz"), "in", expect{true, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf("bar--baz"), "not in", expect{true, false}},
       -                {reflect.Value{}, reflect.ValueOf("foo"), "", expect{false, false}},
       -                {reflect.ValueOf("foo"), reflect.Value{}, "", expect{false, false}},
       -                {reflect.ValueOf((*TstX)(nil)), reflect.ValueOf("foo"), "", expect{false, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf((*TstX)(nil)), "", expect{false, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf(map[int]string{}), "", expect{false, false}},
       -                {reflect.ValueOf("foo"), reflect.ValueOf([]int{1, 2}), "", expect{false, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf([]int{}), "in", expect{false, false}},
       -                {reflect.ValueOf(123), reflect.ValueOf(123), "op", expect{false, true}},
       -        } {
       -                result, err := checkCondition(this.value, this.match, this.op)
       -                if this.expect.isError {
       -                        if err == nil {
       -                                t.Errorf("[%d] checkCondition didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if result != this.expect.result {
       -                                t.Errorf("[%d] check condition %v %s %v, got %v but expected %v", i, this.value, this.op, this.match, result, this.expect.result)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestWhere(t *testing.T) {
       -        // TODO(spf): Put these page tests back in
       -        //page1 := &Page{contentType: "v", Source: Source{File: *source.NewFile("/x/y/z/source.md")}}
       -        //page2 := &Page{contentType: "w", Source: Source{File: *source.NewFile("/y/z/a/source.md")}}
       -
       -        type Mid struct {
       -                Tst TstX
       -        }
       -
       -        for i, this := range []struct {
       -                sequence interface{}
       -                key      interface{}
       -                op       string
       -                match    interface{}
       -                expect   interface{}
       -        }{
       -                {
       -                        sequence: []map[int]string{
       -                                {1: "a", 2: "m"}, {1: "c", 2: "d"}, {1: "e", 3: "m"},
       -                        },
       -                        key: 2, match: "m",
       -                        expect: []map[int]string{
       -                                {1: "a", 2: "m"},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]int{
       -                                {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4},
       -                        },
       -                        key: "b", match: 4,
       -                        expect: []map[string]int{
       -                                {"a": 3, "b": 4},
       -                        },
       -                },
       -                {
       -                        sequence: []TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
       -                        },
       -                        key: "B", match: "f",
       -                        expect: []TstX{
       -                                {A: "e", B: "f"},
       -                        },
       -                },
       -                {
       -                        sequence: []*map[int]string{
       -                                {1: "a", 2: "m"}, {1: "c", 2: "d"}, {1: "e", 3: "m"},
       -                        },
       -                        key: 2, match: "m",
       -                        expect: []*map[int]string{
       -                                {1: "a", 2: "m"},
       -                        },
       -                },
       -                {
       -                        sequence: []*TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
       -                        },
       -                        key: "B", match: "f",
       -                        expect: []*TstX{
       -                                {A: "e", B: "f"},
       -                        },
       -                },
       -                {
       -                        sequence: []*TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "c"},
       -                        },
       -                        key: "TstRp", match: "rc",
       -                        expect: []*TstX{
       -                                {A: "c", B: "d"},
       -                        },
       -                },
       -                {
       -                        sequence: []TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "c"},
       -                        },
       -                        key: "TstRv", match: "rc",
       -                        expect: []TstX{
       -                                {A: "e", B: "c"},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]TstX{
       -                                {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
       -                        },
       -                        key: "foo.B", match: "d",
       -                        expect: []map[string]TstX{
       -                                {"foo": TstX{A: "c", B: "d"}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]TstX{
       -                                {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
       -                        },
       -                        key: ".foo.B", match: "d",
       -                        expect: []map[string]TstX{
       -                                {"foo": TstX{A: "c", B: "d"}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]TstX{
       -                                {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
       -                        },
       -                        key: "foo.TstRv", match: "rd",
       -                        expect: []map[string]TstX{
       -                                {"foo": TstX{A: "c", B: "d"}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]*TstX{
       -                                {"foo": &TstX{A: "a", B: "b"}}, {"foo": &TstX{A: "c", B: "d"}}, {"foo": &TstX{A: "e", B: "f"}},
       -                        },
       -                        key: "foo.TstRp", match: "rc",
       -                        expect: []map[string]*TstX{
       -                                {"foo": &TstX{A: "c", B: "d"}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]Mid{
       -                                {"foo": Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": Mid{Tst: TstX{A: "e", B: "f"}}},
       -                        },
       -                        key: "foo.Tst.B", match: "d",
       -                        expect: []map[string]Mid{
       -                                {"foo": Mid{Tst: TstX{A: "c", B: "d"}}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]Mid{
       -                                {"foo": Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": Mid{Tst: TstX{A: "e", B: "f"}}},
       -                        },
       -                        key: "foo.Tst.TstRv", match: "rd",
       -                        expect: []map[string]Mid{
       -                                {"foo": Mid{Tst: TstX{A: "c", B: "d"}}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]*Mid{
       -                                {"foo": &Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": &Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": &Mid{Tst: TstX{A: "e", B: "f"}}},
       -                        },
       -                        key: "foo.Tst.TstRp", match: "rc",
       -                        expect: []map[string]*Mid{
       -                                {"foo": &Mid{Tst: TstX{A: "c", B: "d"}}},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]int{
       -                                {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6},
       -                        },
       -                        key: "b", op: ">", match: 3,
       -                        expect: []map[string]int{
       -                                {"a": 3, "b": 4}, {"a": 5, "b": 6},
       -                        },
       -                },
       -                {
       -                        sequence: []TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
       -                        },
       -                        key: "B", op: "!=", match: "f",
       -                        expect: []TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"},
       -                        },
       -                },
       -                {
       -                        sequence: []map[string]int{
       -                                {"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6},
       -                        },
       -                        key: "b", op: "in", match: []int{3, 4, 5},
       -                        expect: []map[string]int{
       -                                {"a": 3, "b": 4},
       -                        },
       -                },
       -                {
       -                        sequence: []TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
       -                        },
       -                        key: "B", op: "not in", match: []string{"c", "d", "e"},
       -                        expect: []TstX{
       -                                {A: "a", B: "b"}, {A: "e", B: "f"},
       -                        },
       -                },
       -                {sequence: (*[]TstX)(nil), key: "A", match: "a", expect: false},
       -                {sequence: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},
       -                {sequence: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: false},
       -                {
       -                        sequence: []TstX{
       -                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
       -                        },
       -                        key: "B", op: "op", match: "f",
       -                        expect: false,
       -                },
       -                //{[]*Page{page1, page2}, "Type", "v", []*Page{page1}},
       -                //{[]*Page{page1, page2}, "Section", "y", []*Page{page2}},
       -        } {
       -                var results interface{}
       -                var err error
       -                if len(this.op) > 0 {
       -                        results, err = Where(this.sequence, this.key, this.op, this.match)
       -                } else {
       -                        results, err = Where(this.sequence, this.key, this.match)
       -                }
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] Where didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] failed: %s", i, err)
       -                                continue
       -                        }
       -                        if !reflect.DeepEqual(results, this.expect) {
       -                                t.Errorf("[%d] Where clause matching %v with %v, got %v but expected %v", i, this.key, this.match, results, this.expect)
       -                        }
       -                }
       -        }
       -
       -        var err error
       -        _, err = Where(map[string]int{"a": 1, "b": 2}, "a", []byte("="), 1)
       -        if err == nil {
       -                t.Errorf("Where called with none string op value didn't return an expected error")
       -        }
       -
       -        _, err = Where(map[string]int{"a": 1, "b": 2}, "a", []byte("="), 1, 2)
       -        if err == nil {
       -                t.Errorf("Where called with more than two variable arguments didn't return an expected error")
       -        }
       -
       -        _, err = Where(map[string]int{"a": 1, "b": 2}, "a")
       -        if err == nil {
       -                t.Errorf("Where called with no variable arguments didn't return an expected error")
       -        }
       -}
       -
       -func TestDelimit(t *testing.T) {
       -        for i, this := range []struct {
       -                sequence  interface{}
       -                delimiter interface{}
       -                last      interface{}
       -                expect    template.HTML
       -        }{
       -                {[]string{"class1", "class2", "class3"}, " ", nil, "class1 class2 class3"},
       -                {[]int{1, 2, 3, 4, 5}, ",", nil, "1,2,3,4,5"},
       -                {[]int{1, 2, 3, 4, 5}, ", ", nil, "1, 2, 3, 4, 5"},
       -                {[]string{"class1", "class2", "class3"}, " ", " and ", "class1 class2 and class3"},
       -                {[]int{1, 2, 3, 4, 5}, ",", ",", "1,2,3,4,5"},
       -                {[]int{1, 2, 3, 4, 5}, ", ", ", and ", "1, 2, 3, 4, and 5"},
       -                // test maps with and without sorting required
       -                {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "--", nil, "10--20--30--40--50"},
       -                {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "--", nil, "30--20--10--40--50"},
       -                {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, "--", nil, "10--20--30--40--50"},
       -                {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, "--", nil, "30--20--10--40--50"},
       -                {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, "--", nil, "50--40--10--30--20"},
       -                {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, "--", nil, "10--20--30--40--50"},
       -                {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, "--", nil, "30--20--10--40--50"},
       -                {map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, "--", nil, "30--20--10--40--50"},
       -                // test maps with a last delimiter
       -                {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "--", "--and--", "10--20--30--40--and--50"},
       -                {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "--", "--and--", "30--20--10--40--and--50"},
       -                {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, "--", "--and--", "10--20--30--40--and--50"},
       -                {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, "--", "--and--", "30--20--10--40--and--50"},
       -                {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, "--", "--and--", "50--40--10--30--and--20"},
       -                {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, "--", "--and--", "10--20--30--40--and--50"},
       -                {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, "--", "--and--", "30--20--10--40--and--50"},
       -                {map[float64]string{3.5: "10", 2.5: "20", 1.5: "30", 4.5: "40", 5.5: "50"}, "--", "--and--", "30--20--10--40--and--50"},
       -        } {
       -                var result template.HTML
       -                var err error
       -                if this.last == nil {
       -                        result, err = Delimit(this.sequence, this.delimiter)
       -                } else {
       -                        result, err = Delimit(this.sequence, this.delimiter, this.last)
       -                }
       -                if err != nil {
       -                        t.Errorf("[%d] failed: %s", i, err)
       -                        continue
       -                }
       -                if !reflect.DeepEqual(result, this.expect) {
       -                        t.Errorf("[%d] Delimit called on sequence: %v | delimiter: `%v` | last: `%v`, got %v but expected %v", i, this.sequence, this.delimiter, this.last, result, this.expect)
       -                }
       -        }
       -}
       -
       -func TestSort(t *testing.T) {
       -        type ts struct {
       -                MyInt    int
       -                MyFloat  float64
       -                MyString string
       -        }
       -        for i, this := range []struct {
       -                sequence    interface{}
       -                sortByField interface{}
       -                sortAsc     string
       -                expect      []interface{}
       -        }{
       -                {[]string{"class1", "class2", "class3"}, nil, "asc", []interface{}{"class1", "class2", "class3"}},
       -                {[]string{"class3", "class1", "class2"}, nil, "asc", []interface{}{"class1", "class2", "class3"}},
       -                {[]int{1, 2, 3, 4, 5}, nil, "asc", []interface{}{1, 2, 3, 4, 5}},
       -                {[]int{5, 4, 3, 1, 2}, nil, "asc", []interface{}{1, 2, 3, 4, 5}},
       -                // test map sorting by keys
       -                {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, nil, "asc", []interface{}{10, 20, 30, 40, 50}},
       -                {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, nil, "asc", []interface{}{30, 20, 10, 40, 50}},
       -                {map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, nil, "asc", []interface{}{"10", "20", "30", "40", "50"}},
       -                {map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, nil, "asc", []interface{}{"30", "20", "10", "40", "50"}},
       -                {map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, nil, "asc", []interface{}{"50", "40", "10", "30", "20"}},
       -                {map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, nil, "asc", []interface{}{"10", "20", "30", "40", "50"}},
       -                {map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, nil, "asc", []interface{}{"30", "20", "10", "40", "50"}},
       -                {map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, nil, "asc", []interface{}{"30", "20", "10", "40", "50"}},
       -                // test map sorting by value
       -                {map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "value", "asc", []interface{}{10, 20, 30, 40, 50}},
       -                {map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "value", "asc", []interface{}{10, 20, 30, 40, 50}},
       -                // test map sorting by field value
       -                {
       -                        map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}},
       -                        "MyInt",
       -                        "asc",
       -                        []interface{}{ts{10, 10.5, "ten"}, ts{20, 20.5, "twenty"}, ts{30, 30.5, "thirty"}, ts{40, 40.5, "forty"}, ts{50, 50.5, "fifty"}},
       -                },
       -                {
       -                        map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}},
       -                        "MyFloat",
       -                        "asc",
       -                        []interface{}{ts{10, 10.5, "ten"}, ts{20, 20.5, "twenty"}, ts{30, 30.5, "thirty"}, ts{40, 40.5, "forty"}, ts{50, 50.5, "fifty"}},
       -                },
       -                {
       -                        map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}},
       -                        "MyString",
       -                        "asc",
       -                        []interface{}{ts{50, 50.5, "fifty"}, ts{40, 40.5, "forty"}, ts{10, 10.5, "ten"}, ts{30, 30.5, "thirty"}, ts{20, 20.5, "twenty"}},
       -                },
       -                // Test sort desc
       -                {[]string{"class1", "class2", "class3"}, "value", "desc", []interface{}{"class3", "class2", "class1"}},
       -                {[]string{"class3", "class1", "class2"}, "value", "desc", []interface{}{"class3", "class2", "class1"}},
       -        } {
       -                var result []interface{}
       -                var err error
       -                if this.sortByField == nil {
       -                        result, err = Sort(this.sequence)
       -                } else {
       -                        result, err = Sort(this.sequence, this.sortByField, this.sortAsc)
       -                }
       -                if err != nil {
       -                        t.Errorf("[%d] failed: %s", i, err)
       -                        continue
       -                }
       -                if !reflect.DeepEqual(result, this.expect) {
       -                        t.Errorf("[%d] Sort called on sequence: %v | sortByField: `%v` | got %v but expected %v", i, this.sequence, this.sortByField, result, this.expect)
       -                }
       -        }
       -}
       -
       -func TestReturnWhenSet(t *testing.T) {
       -        for i, this := range []struct {
       -                data   interface{}
       -                key    interface{}
       -                expect interface{}
       -        }{
       -                {[]int{1, 2, 3}, 1, int64(2)},
       -                {[]uint{1, 2, 3}, 1, uint64(2)},
       -                {[]float64{1.1, 2.2, 3.3}, 1, float64(2.2)},
       -                {[]string{"foo", "bar", "baz"}, 1, "bar"},
       -                {[]TstX{{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"}}, 1, ""},
       -                {map[string]int{"foo": 1, "bar": 2, "baz": 3}, "bar", int64(2)},
       -                {map[string]uint{"foo": 1, "bar": 2, "baz": 3}, "bar", uint64(2)},
       -                {map[string]float64{"foo": 1.1, "bar": 2.2, "baz": 3.3}, "bar", float64(2.2)},
       -                {map[string]string{"foo": "FOO", "bar": "BAR", "baz": "BAZ"}, "bar", "BAR"},
       -                {map[string]TstX{"foo": {A: "a", B: "b"}, "bar": {A: "c", B: "d"}, "baz": {A: "e", B: "f"}}, "bar", ""},
       -                {(*[]string)(nil), "bar", ""},
       -        } {
       -                result := ReturnWhenSet(this.data, this.key)
       -                if !reflect.DeepEqual(result, this.expect) {
       -                        t.Errorf("[%d] ReturnWhenSet got %v (type %v) but expected %v (type %v)", i, result, reflect.TypeOf(result), this.expect, reflect.TypeOf(this.expect))
       -                }
       -        }
       -}
       -
       -func TestMarkdownify(t *testing.T) {
       -
       -        result := Markdownify("Hello **World!**")
       -
       -        expect := template.HTML("Hello <strong>World!</strong>")
       -
       -        if result != expect {
       -                t.Errorf("Markdownify: got '%s', expected '%s'", result, expect)
       -        }
       -}
       -
       -func TestApply(t *testing.T) {
       -        strings := []interface{}{"a\n", "b\n"}
       -        noStringers := []interface{}{tstNoStringer{}, tstNoStringer{}}
       -
       -        var nilErr *error = nil
       -
       -        chomped, _ := Apply(strings, "chomp", ".")
       -        assert.Equal(t, []interface{}{"a", "b"}, chomped)
       -
       -        chomped, _ = Apply(strings, "chomp", "c\n")
       -        assert.Equal(t, []interface{}{"c", "c"}, chomped)
       -
       -        chomped, _ = Apply(nil, "chomp", ".")
       -        assert.Equal(t, []interface{}{}, chomped)
       -
       -        _, err := Apply(strings, "apply", ".")
       -        if err == nil {
       -                t.Errorf("apply with apply should fail")
       -        }
       -
       -        _, err = Apply(nilErr, "chomp", ".")
       -        if err == nil {
       -                t.Errorf("apply with nil in seq should fail")
       -        }
       -
       -        _, err = Apply(strings, "dobedobedo", ".")
       -        if err == nil {
       -                t.Errorf("apply with unknown func should fail")
       -        }
       -
       -        _, err = Apply(noStringers, "chomp", ".")
       -        if err == nil {
       -                t.Errorf("apply when func fails should fail")
       -        }
       -
       -        _, err = Apply(tstNoStringer{}, "chomp", ".")
       -        if err == nil {
       -                t.Errorf("apply with non-sequence should fail")
       -        }
       -
       -}
       -
       -func TestChomp(t *testing.T) {
       -        base := "\n This is\na story "
       -        for i, item := range []string{
       -                "\n", "\n\n",
       -                "\r", "\r\r",
       -                "\r\n", "\r\n\r\n",
       -        } {
       -                chomped, _ := Chomp(base + item)
       -
       -                if chomped != base {
       -                        t.Errorf("[%d] Chomp failed, got '%v'", i, chomped)
       -                }
       -
       -                _, err := Chomp(tstNoStringer{})
       -
       -                if err == nil {
       -                        t.Errorf("Chomp should fail")
       -                }
       -        }
       -}
       -
       -func TestReplace(t *testing.T) {
       -        v, _ := Replace("aab", "a", "b")
       -        assert.Equal(t, "bbb", v)
       -        v, _ = Replace("11a11", 1, 2)
       -        assert.Equal(t, "22a22", v)
       -        v, _ = Replace(12345, 1, 2)
       -        assert.Equal(t, "22345", v)
       -        _, e := Replace(tstNoStringer{}, "a", "b")
       -        assert.NotNil(t, e, "tstNoStringer isn't trimmable")
       -        _, e = Replace("a", tstNoStringer{}, "b")
       -        assert.NotNil(t, e, "tstNoStringer cannot be converted to string")
       -        _, e = Replace("a", "b", tstNoStringer{})
       -        assert.NotNil(t, e, "tstNoStringer cannot be converted to string")
       -}
       -
       -func TestTrim(t *testing.T) {
       -        v, _ := Trim("1234 my way 13", "123")
       -        assert.Equal(t, "4 my way ", v)
       -        v, _ = Trim("   my way    ", " ")
       -        assert.Equal(t, "my way", v)
       -        v, _ = Trim(1234, "14")
       -        assert.Equal(t, "23", v)
       -        _, e := Trim(tstNoStringer{}, " ")
       -        assert.NotNil(t, e, "tstNoStringer isn't trimmable")
       -}
       -
       -func TestDateFormat(t *testing.T) {
       -        for i, this := range []struct {
       -                layout string
       -                value  interface{}
       -                expect interface{}
       -        }{
       -                {"Monday, Jan 2, 2006", "2015-01-21", "Wednesday, Jan 21, 2015"},
       -                {"Monday, Jan 2, 2006", time.Date(2015, time.January, 21, 0, 0, 0, 0, time.UTC), "Wednesday, Jan 21, 2015"},
       -                {"This isn't a date layout string", "2015-01-21", "This isn't a date layout string"},
       -                {"Monday, Jan 2, 2006", 1421733600, false},
       -                {"Monday, Jan 2, 2006", 1421733600.123, false},
       -        } {
       -                result, err := DateFormat(this.layout, this.value)
       -                if b, ok := this.expect.(bool); ok && !b {
       -                        if err == nil {
       -                                t.Errorf("[%d] DateFormat didn't return an expected error", i)
       -                        }
       -                } else {
       -                        if err != nil {
       -                                t.Errorf("[%d] DateFormat failed: %s", i, err)
       -                                continue
       -                        }
       -                        if result != this.expect {
       -                                t.Errorf("[%d] DateFormat got %v but expected %v", i, result, this.expect)
       -                        }
       -                }
       -        }
       -}
       -
       -func TestSafeHTML(t *testing.T) {
       -        for i, this := range []struct {
       -                str                 string
       -                tmplStr             string
       -                expectWithoutEscape string
       -                expectWithEscape    string
       -        }{
       -                {`<div></div>`, `{{ . }}`, `&lt;div&gt;&lt;/div&gt;`, `<div></div>`},
       -        } {
       -                tmpl, err := template.New("test").Parse(this.tmplStr)
       -                if err != nil {
       -                        t.Errorf("[%d] unable to create new html template %q: %s", i, this.tmplStr, err)
       -                        continue
       -                }
       -
       -                buf := new(bytes.Buffer)
       -                err = tmpl.Execute(buf, this.str)
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithoutEscape {
       -                        t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
       -                }
       -
       -                buf.Reset()
       -                err = tmpl.Execute(buf, SafeHTML(this.str))
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeHTML returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithEscape {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeHTML, got %v but expected %v", i, buf.String(), this.expectWithEscape)
       -                }
       -        }
       -}
       -
       -func TestSafeHTMLAttr(t *testing.T) {
       -        for i, this := range []struct {
       -                str                 string
       -                tmplStr             string
       -                expectWithoutEscape string
       -                expectWithEscape    string
       -        }{
       -                {`href="irc://irc.freenode.net/#golang"`, `<a {{ . }}>irc</a>`, `<a ZgotmplZ>irc</a>`, `<a href="irc://irc.freenode.net/#golang">irc</a>`},
       -        } {
       -                tmpl, err := template.New("test").Parse(this.tmplStr)
       -                if err != nil {
       -                        t.Errorf("[%d] unable to create new html template %q: %s", i, this.tmplStr, err)
       -                        continue
       -                }
       -
       -                buf := new(bytes.Buffer)
       -                err = tmpl.Execute(buf, this.str)
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithoutEscape {
       -                        t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
       -                }
       -
       -                buf.Reset()
       -                err = tmpl.Execute(buf, SafeHTMLAttr(this.str))
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeHTMLAttr returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithEscape {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeHTMLAttr, got %v but expected %v", i, buf.String(), this.expectWithEscape)
       -                }
       -        }
       -}
       -
       -func TestSafeCSS(t *testing.T) {
       -        for i, this := range []struct {
       -                str                 string
       -                tmplStr             string
       -                expectWithoutEscape string
       -                expectWithEscape    string
       -        }{
       -                {`width: 60px;`, `<div style="{{ . }}"></div>`, `<div style="ZgotmplZ"></div>`, `<div style="width: 60px;"></div>`},
       -        } {
       -                tmpl, err := template.New("test").Parse(this.tmplStr)
       -                if err != nil {
       -                        t.Errorf("[%d] unable to create new html template %q: %s", i, this.tmplStr, err)
       -                        continue
       -                }
       -
       -                buf := new(bytes.Buffer)
       -                err = tmpl.Execute(buf, this.str)
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithoutEscape {
       -                        t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
       -                }
       -
       -                buf.Reset()
       -                err = tmpl.Execute(buf, SafeCSS(this.str))
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeCSS returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithEscape {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeCSS, got %v but expected %v", i, buf.String(), this.expectWithEscape)
       -                }
       -        }
       -}
       -
       -func TestSafeURL(t *testing.T) {
       -        for i, this := range []struct {
       -                str                 string
       -                tmplStr             string
       -                expectWithoutEscape string
       -                expectWithEscape    string
       -        }{
       -                {`irc://irc.freenode.net/#golang`, `<a href="{{ . }}">IRC</a>`, `<a href="#ZgotmplZ">IRC</a>`, `<a href="irc://irc.freenode.net/#golang">IRC</a>`},
       -        } {
       -                tmpl, err := template.New("test").Parse(this.tmplStr)
       -                if err != nil {
       -                        t.Errorf("[%d] unable to create new html template %q: %s", i, this.tmplStr, err)
       -                        continue
       -                }
       -
       -                buf := new(bytes.Buffer)
       -                err = tmpl.Execute(buf, this.str)
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithoutEscape {
       -                        t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
       -                }
       -
       -                buf.Reset()
       -                err = tmpl.Execute(buf, SafeURL(this.str))
       -                if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeURL returns unexpected error: %s", i, err)
       -                }
       -                if buf.String() != this.expectWithEscape {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeURL, got %v but expected %v", i, buf.String(), this.expectWithEscape)
       -                }
       -        }
       -}
       +// TODO(bep) test it