diff options
author | Bjørn Erik Pedersen <[email protected]> | 2017-05-01 18:40:34 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2017-05-01 21:44:15 +0200 |
commit | 690b0f8ff5795318dfa3834a5a75d6623e7d934a (patch) | |
tree | 1112306f4c6fecc0966d880dec702c3804633deb /tpl | |
parent | e2b067f0504ba41ef45786e2f83d7002bd13a7eb (diff) | |
download | hugo-690b0f8ff5795318dfa3834a5a75d6623e7d934a.tar.gz hugo-690b0f8ff5795318dfa3834a5a75d6623e7d934a.zip |
tpl: Add docshelper for template funcs
And fix some other minor related issues.
Updates #3418
Diffstat (limited to 'tpl')
-rw-r--r-- | tpl/cast/docshelper.go | 41 | ||||
-rw-r--r-- | tpl/cast/init.go | 28 | ||||
-rw-r--r-- | tpl/collections/init.go | 150 | ||||
-rw-r--r-- | tpl/compare/init.go | 60 | ||||
-rw-r--r-- | tpl/crypto/init.go | 39 | ||||
-rw-r--r-- | tpl/data/init.go | 22 | ||||
-rw-r--r-- | tpl/encoding/init.go | 39 | ||||
-rw-r--r-- | tpl/fmt/fmt.go | 13 | ||||
-rw-r--r-- | tpl/fmt/init.go | 35 | ||||
-rw-r--r-- | tpl/images/init.go | 17 | ||||
-rw-r--r-- | tpl/inflect/init.go | 43 | ||||
-rw-r--r-- | tpl/internal/templatefuncRegistry_test.go | 33 | ||||
-rw-r--r-- | tpl/internal/templatefuncsRegistry.go | 83 | ||||
-rw-r--r-- | tpl/lang/init.go | 18 | ||||
-rw-r--r-- | tpl/math/init.go | 64 | ||||
-rw-r--r-- | tpl/os/init.go | 34 | ||||
-rw-r--r-- | tpl/partials/init.go | 25 | ||||
-rw-r--r-- | tpl/safe/init.go | 67 | ||||
-rw-r--r-- | tpl/strings/init.go | 152 | ||||
-rw-r--r-- | tpl/time/init.go | 34 | ||||
-rw-r--r-- | tpl/tplimpl/template_funcs.go | 10 | ||||
-rw-r--r-- | tpl/tplimpl/template_funcs_test.go | 28 | ||||
-rw-r--r-- | tpl/transform/init.go | 99 | ||||
-rw-r--r-- | tpl/urls/init.go | 56 |
24 files changed, 842 insertions, 348 deletions
diff --git a/tpl/cast/docshelper.go b/tpl/cast/docshelper.go new file mode 100644 index 000000000..5220ca570 --- /dev/null +++ b/tpl/cast/docshelper.go @@ -0,0 +1,41 @@ +// Copyright 2017 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache 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://www.apache.org/licenses/LICENSE-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 cast + +import ( + "github.com/spf13/hugo/deps" + "github.com/spf13/hugo/docshelper" + "github.com/spf13/hugo/tpl/internal" +) + +// This file provides documentation support and is randomly put into this package. +func init() { + docsProvider := func() map[string]interface{} { + docs := make(map[string]interface{}) + d := &deps.Deps{} + + var namespaces []*internal.TemplateFuncsNamespace + + for _, nsf := range internal.TemplateFuncsNamespaceRegistry { + nf := nsf(d) + namespaces = append(namespaces, nf) + + } + + docs["funcs"] = namespaces + return docs + } + + docshelper.AddDocProvider("tpl", docsProvider) +} diff --git a/tpl/cast/init.go b/tpl/cast/init.go index acddaa91a..1c737ee58 100644 --- a/tpl/cast/init.go +++ b/tpl/cast/init.go @@ -24,21 +24,27 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ "1234" | int | printf "%T" }}`, `int`}, - {`{{ 1234 | string | printf "%T" }}`, `string`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "int": ctx.ToInt, - "string": ctx.ToString, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.ToInt, + []string{"int"}, + [][2]string{ + {`{{ "1234" | int | printf "%T" }}`, `int`}, + }, + ) + + ns.AddMethodMapping(ctx.ToString, + []string{"string"}, + [][2]string{ + {`{{ 1234 | string | printf "%T" }}`, `string`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/collections/init.go b/tpl/collections/init.go index 29f6809c3..289228901 100644 --- a/tpl/collections/init.go +++ b/tpl/collections/init.go @@ -24,48 +24,122 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`}, - {`{{ echoParam .Params "langCode" }}`, `en`}, - {`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`}, - { - `{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`, - `bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`}, - { - `<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`, - `<a href="https://www.google.com?page=3&q=test">Search</a>`}, - {`{{ slice "B" "C" "A" | sort }}`, `[A B C]`}, - {`{{ seq 3 }}`, `[1 2 3]`}, - {`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "after": ctx.After, - "apply": ctx.Apply, - "delimit": ctx.Delimit, - "dict": ctx.Dictionary, - "echoParam": ctx.EchoParam, - "first": ctx.First, - "in": ctx.In, - "index": ctx.Index, - "intersect": ctx.Intersect, - "isSet": ctx.IsSet, - "isset": ctx.IsSet, - "last": ctx.Last, - "querify": ctx.Querify, - "shuffle": ctx.Shuffle, - "slice": ctx.Slice, - "sort": ctx.Sort, - "union": ctx.Union, - "where": ctx.Where, - "seq": ctx.Seq, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.After, + []string{"after"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Apply, + []string{"apply"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Delimit, + []string{"delimit"}, + [][2]string{ + {`{{ delimit (slice "A" "B" "C") ", " " and " }}`, `A, B and C`}, + }, + ) + + ns.AddMethodMapping(ctx.Dictionary, + []string{"dict"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.EchoParam, + []string{"echoParam"}, + [][2]string{ + {`{{ echoParam .Params "langCode" }}`, `en`}, + }, + ) + + ns.AddMethodMapping(ctx.First, + []string{"first"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.In, + []string{"in"}, + [][2]string{ + {`{{ if in "this string contains a substring" "substring" }}Substring found!{{ end }}`, `Substring found!`}, + }, + ) + + ns.AddMethodMapping(ctx.Index, + []string{"index"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Intersect, + []string{"intersect"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.IsSet, + []string{"isSet", "isset"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Last, + []string{"last"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Querify, + []string{"querify"}, + [][2]string{ + { + `{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") | safeHTML }}`, + `bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose`}, + { + `<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`, + `<a href="https://www.google.com?page=3&q=test">Search</a>`}, + }, + ) + + ns.AddMethodMapping(ctx.Shuffle, + []string{"shuffle"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Slice, + []string{"slice"}, + [][2]string{ + {`{{ slice "B" "C" "A" | sort }}`, `[A B C]`}, + }, + ) + + ns.AddMethodMapping(ctx.Sort, + []string{"sort"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Union, + []string{"union"}, + [][2]string{ + {`{{ union (slice 1 2 3) (slice 3 4 5) }}`, `[1 2 3 4 5]`}, + }, + ) + + ns.AddMethodMapping(ctx.Where, + []string{"where"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Seq, + []string{"seq"}, + [][2]string{ + {`{{ seq 3 }}`, `[1 2 3]`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/compare/init.go b/tpl/compare/init.go index bf8227353..0285abff5 100644 --- a/tpl/compare/init.go +++ b/tpl/compare/init.go @@ -24,27 +24,53 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ if eq .Section "blog" }}current{{ end }}`, `current`}, - {`{{ "Hugo Rocks!" | default "Hugo Rules!" }}`, `Hugo Rocks!`}, - {`{{ "" | default "Hugo Rules!" }}`, `Hugo Rules!`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "default": ctx.Default, - "eq": ctx.Eq, - "ge": ctx.Ge, - "gt": ctx.Gt, - "le": ctx.Le, - "lt": ctx.Lt, - "ne": ctx.Ne, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Default, + []string{"default"}, + [][2]string{ + {`{{ "Hugo Rocks!" | default "Hugo Rules!" }}`, `Hugo Rocks!`}, + {`{{ "" | default "Hugo Rules!" }}`, `Hugo Rules!`}, + }, + ) + + ns.AddMethodMapping(ctx.Eq, + []string{"eq"}, + [][2]string{ + {`{{ if eq .Section "blog" }}current{{ end }}`, `current`}, + }, + ) + + ns.AddMethodMapping(ctx.Ge, + []string{"ge"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Gt, + []string{"gt"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Le, + []string{"le"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Lt, + []string{"lt"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Ne, + []string{"ne"}, + [][2]string{}, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/crypto/init.go b/tpl/crypto/init.go index 7c1899f88..a47c3369f 100644 --- a/tpl/crypto/init.go +++ b/tpl/crypto/init.go @@ -24,24 +24,35 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ md5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, - {`{{ crypto.MD5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, - {`{{ sha1 "Hello world, gophers!" }}`, `c8b5b0e33d408246e30f53e32b8f7627a7a649d4`}, - {`{{ sha256 "Hello world, gophers!" }}`, `6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "md5": ctx.MD5, - "sha1": ctx.SHA1, - "sha256": ctx.SHA256, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.MD5, + []string{"md5"}, + [][2]string{ + {`{{ md5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, + {`{{ crypto.MD5 "Hello world, gophers!" }}`, `b3029f756f98f79e7f1b7f1d1f0dd53b`}, + }, + ) + + ns.AddMethodMapping(ctx.SHA1, + []string{"sha1"}, + [][2]string{ + {`{{ sha1 "Hello world, gophers!" }}`, `c8b5b0e33d408246e30f53e32b8f7627a7a649d4`}, + }, + ) + + ns.AddMethodMapping(ctx.SHA256, + []string{"sha256"}, + [][2]string{ + {`{{ sha256 "Hello world, gophers!" }}`, `6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/data/init.go b/tpl/data/init.go index 476e9ab75..e9e4ca2f9 100644 --- a/tpl/data/init.go +++ b/tpl/data/init.go @@ -24,19 +24,21 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "getCSV": ctx.GetCSV, - "getJSON": ctx.GetJSON, - }, - Examples: examples, } + + ns.AddMethodMapping(ctx.GetCSV, + []string{"getCSV"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.GetJSON, + []string{"getJSON"}, + [][2]string{}, + ) + return ns } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/encoding/init.go b/tpl/encoding/init.go index 5bc0eb145..b46394203 100644 --- a/tpl/encoding/init.go +++ b/tpl/encoding/init.go @@ -24,24 +24,35 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ (slice "A" "B" "C") | jsonify }}`, `["A","B","C"]`}, - {`{{ "SGVsbG8gd29ybGQ=" | base64Decode }}`, `Hello world`}, - {`{{ 42 | base64Encode | base64Decode }}`, `42`}, - {`{{ "Hello world" | base64Encode }}`, `SGVsbG8gd29ybGQ=`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "base64Decode": ctx.Base64Decode, - "base64Encode": ctx.Base64Encode, - "jsonify": ctx.Jsonify, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Base64Decode, + []string{"base64Decode"}, + [][2]string{ + {`{{ "SGVsbG8gd29ybGQ=" | base64Decode }}`, `Hello world`}, + {`{{ 42 | base64Encode | base64Decode }}`, `42`}, + }, + ) + + ns.AddMethodMapping(ctx.Base64Encode, + []string{"base64Encode"}, + [][2]string{ + {`{{ "Hello world" | base64Encode }}`, `SGVsbG8gd29ybGQ=`}, + }, + ) + + ns.AddMethodMapping(ctx.Jsonify, + []string{"jsonify"}, + [][2]string{ + {`{{ (slice "A" "B" "C") | jsonify }}`, `["A","B","C"]`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/fmt/fmt.go b/tpl/fmt/fmt.go index 5e320fede..ca31ec522 100644 --- a/tpl/fmt/fmt.go +++ b/tpl/fmt/fmt.go @@ -26,14 +26,15 @@ func New() *Namespace { type Namespace struct { } -func (ns *Namespace) Print(a ...interface{}) (n int, err error) { - return _fmt.Print(a...) +func (ns *Namespace) Print(a ...interface{}) string { + return _fmt.Sprint(a...) } -func (ns *Namespace) Printf(format string, a ...interface{}) (n int, err error) { - return _fmt.Printf(format, a...) +func (ns *Namespace) Printf(format string, a ...interface{}) string { + return _fmt.Sprintf(format, a...) + } -func (ns *Namespace) Println(a ...interface{}) (n int, err error) { - return _fmt.Println(a...) +func (ns *Namespace) Println(a ...interface{}) string { + return _fmt.Sprintln(a...) } diff --git a/tpl/fmt/init.go b/tpl/fmt/init.go index 0f4296263..98070b777 100644 --- a/tpl/fmt/init.go +++ b/tpl/fmt/init.go @@ -24,18 +24,33 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ print "works!" }}`, `works!`}, - {`{{ printf "%s!" "works" }}`, `works!`}, - {`{{ println "works!" }}`, "works!\n"}, + ns := &internal.TemplateFuncsNamespace{ + Name: name, + Context: func() interface{} { return ctx }, } - return &internal.TemplateFuncsNamespace{ - Name: name, - Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{}, - Examples: examples, - } + ns.AddMethodMapping(ctx.Print, + []string{"print"}, + [][2]string{ + {`{{ print "works!" }}`, `works!`}, + }, + ) + + ns.AddMethodMapping(ctx.Println, + []string{"println"}, + [][2]string{ + {`{{ println "works!" }}`, "works!\n"}, + }, + ) + + ns.AddMethodMapping(ctx.Printf, + []string{"printf"}, + [][2]string{ + {`{{ printf "%s!" "works" }}`, `works!`}, + }, + ) + + return ns } diff --git a/tpl/images/init.go b/tpl/images/init.go index 0c2cb57c4..8e829f300 100644 --- a/tpl/images/init.go +++ b/tpl/images/init.go @@ -24,19 +24,18 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "imageConfig": ctx.Config, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Config, + []string{"imageConfig"}, + [][2]string{}, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/inflect/init.go b/tpl/inflect/init.go index b42ae5af3..50d012d35 100644 --- a/tpl/inflect/init.go +++ b/tpl/inflect/init.go @@ -24,26 +24,37 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ humanize "my-first-post" }}`, `My first post`}, - {`{{ humanize "myCamelPost" }}`, `My camel post`}, - {`{{ humanize "52" }}`, `52nd`}, - {`{{ humanize 103 }}`, `103rd`}, - {`{{ "cat" | pluralize }}`, `cats`}, - {`{{ "cats" | singularize }}`, `cat`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "humanize": ctx.Humanize, - "pluralize": ctx.Pluralize, - "singularize": ctx.Singularize, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Humanize, + []string{"humanize"}, + [][2]string{ + {`{{ humanize "my-first-post" }}`, `My first post`}, + {`{{ humanize "myCamelPost" }}`, `My camel post`}, + {`{{ humanize "52" }}`, `52nd`}, + {`{{ humanize 103 }}`, `103rd`}, + }, + ) + + ns.AddMethodMapping(ctx.Pluralize, + []string{"pluralize"}, + [][2]string{ + {`{{ "cat" | pluralize }}`, `cats`}, + }, + ) + + ns.AddMethodMapping(ctx.Singularize, + []string{"singularize"}, + [][2]string{ + {`{{ "cats" | singularize }}`, `cat`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/internal/templatefuncRegistry_test.go b/tpl/internal/templatefuncRegistry_test.go new file mode 100644 index 000000000..dfc4ba09b --- /dev/null +++ b/tpl/internal/templatefuncRegistry_test.go @@ -0,0 +1,33 @@ +// Copyright 2017 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache 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://www.apache.org/licenses/LICENSE-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 internal + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +type Test struct { +} + +func (t *Test) MyTestMethod() string { + return "abcde" +} + +func TestMethodToName(t *testing.T) { + test := &Test{} + + require.Equal(t, "MyTestMethod", methodToName(test.MyTestMethod)) +} diff --git a/tpl/internal/templatefuncsRegistry.go b/tpl/internal/templatefuncsRegistry.go index aa3196ca3..c9c931579 100644 --- a/tpl/internal/templatefuncsRegistry.go +++ b/tpl/internal/templatefuncsRegistry.go @@ -16,6 +16,12 @@ package internal import ( + "encoding/json" + "path/filepath" + "reflect" + "runtime" + "strings" + "github.com/spf13/hugo/deps" ) @@ -32,12 +38,46 @@ type TemplateFuncsNamespace struct { // This is the method receiver. Context interface{} + // Additional info, aliases and examples, per method name. + MethodMappings map[string]TemplateFuncMethodMapping +} + +func (t *TemplateFuncsNamespace) AddMethodMapping(m interface{}, aliases []string, examples [][2]string) { + if t.MethodMappings == nil { + t.MethodMappings = make(map[string]TemplateFuncMethodMapping) + } + + name := methodToName(m) + + // sanity check + for _, e := range examples { + if e[0] == "" { + panic(t.Name + ": Empty example for " + name) + } + } + for _, a := range aliases { + if a == "" { + panic(t.Name + ": Empty alias for " + name) + } + } + + t.MethodMappings[name] = TemplateFuncMethodMapping{ + Method: m, + Aliases: aliases, + Examples: examples, + } + +} + +type TemplateFuncMethodMapping struct { + Method interface{} + // Any template funcs aliases. This is mainly motivated by keeping // backwards compability, but some new template funcs may also make // sense to give short and snappy aliases. // Note that these aliases are global and will be merged, so the last // key will win. - Aliases map[string]interface{} + Aliases []string // A slice of input/expected examples. // We keep it a the namespace level for now, but may find a way to keep track @@ -45,3 +85,44 @@ type TemplateFuncsNamespace struct { // Some of these, hopefully just a few, may depend on some test data to run. Examples [][2]string } + +func methodToName(m interface{}) string { + name := runtime.FuncForPC(reflect.ValueOf(m).Pointer()).Name() + name = filepath.Ext(name) + name = strings.TrimPrefix(name, ".") + name = strings.TrimSuffix(name, "-fm") + return name +} + +func (t *TemplateFuncsNamespace) MarshalJSON() ([]byte, error) { + type Func struct { + Name string + Description string // TODO(bep) + Aliases []string + Examples [][2]string + } + // TODO(bep) map/lookup from docs template Namespace + Func name. + var funcs []Func + + ctx := t.Context.(func() interface{})() + ctxType := reflect.TypeOf(ctx) + for i := 0; i < ctxType.NumMethod(); i++ { + method := ctxType.Method(i) + f := Func{ + Name: method.Name, + } + if mapping, ok := t.MethodMappings[method.Name]; ok { + f.Aliases = mapping.Aliases + f.Examples = mapping.Examples + } + funcs = append(funcs, f) + } + + return json.Marshal(&struct { + Name string + Funcs []Func + }{ + Name: t.Name, + Funcs: funcs, + }) +} diff --git a/tpl/lang/init.go b/tpl/lang/init.go index a902c7a66..6cf8e790d 100644 --- a/tpl/lang/init.go +++ b/tpl/lang/init.go @@ -24,20 +24,18 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "i18n": ctx.Translate, - "T": ctx.Translate, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Translate, + []string{"i18n", "T"}, + [][2]string{}, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/math/init.go b/tpl/math/init.go index 69ba2cc17..65b22c516 100644 --- a/tpl/math/init.go +++ b/tpl/math/init.go @@ -24,29 +24,55 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {"{{add 1 2}}", "3"}, - {"{{div 6 3}}", "2"}, - {"{{mod 15 3}}", "0"}, - {"{{modBool 15 3}}", "true"}, - {"{{mul 2 3}}", "6"}, - {"{{sub 3 2}}", "1"}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "add": ctx.Add, - "div": ctx.Div, - "mod": ctx.Mod, - "modBool": ctx.ModBool, - "mul": ctx.Mul, - "sub": ctx.Sub, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Add, + []string{"add"}, + [][2]string{ + {"{{add 1 2}}", "3"}, + }, + ) + + ns.AddMethodMapping(ctx.Div, + []string{"div"}, + [][2]string{ + {"{{div 6 3}}", "2"}, + }, + ) + + ns.AddMethodMapping(ctx.Mod, + []string{"mod"}, + [][2]string{ + {"{{mod 15 3}}", "0"}, + }, + ) + + ns.AddMethodMapping(ctx.ModBool, + []string{"modBool"}, + [][2]string{ + {"{{modBool 15 3}}", "true"}, + }, + ) + + ns.AddMethodMapping(ctx.Mul, + []string{"mul"}, + [][2]string{ + {"{{mul 2 3}}", "6"}, + }, + ) + + ns.AddMethodMapping(ctx.Sub, + []string{"sub"}, + [][2]string{ + {"{{sub 3 2}}", "1"}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/os/init.go b/tpl/os/init.go index d03ad5f03..264afd43a 100644 --- a/tpl/os/init.go +++ b/tpl/os/init.go @@ -24,22 +24,32 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {`{{ range (readDir ".") }}{{ .Name }}{{ end }}`, "README.txt"}, - {`{{ readFile "README.txt" }}`, `Hugo Rocks!`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "getenv": ctx.Getenv, - "readDir": ctx.ReadDir, - "readFile": ctx.ReadFile, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Getenv, + []string{"getenv"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.ReadDir, + []string{"readDir"}, + [][2]string{ + {`{{ range (readDir ".") }}{{ .Name }}{{ end }}`, "README.txt"}, + }, + ) + + ns.AddMethodMapping(ctx.ReadFile, + []string{"readFile"}, + [][2]string{ + {`{{ readFile "README.txt" }}`, `Hugo Rocks!`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/partials/init.go b/tpl/partials/init.go index a9d1f82fe..4ee3faf19 100644 --- a/tpl/partials/init.go +++ b/tpl/partials/init.go @@ -24,20 +24,25 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {`{{ partial "header.html" . }}`, `<title>Hugo Rocks!</title>`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "partial": ctx.Include, - "partialCached": ctx.getCached, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Include, + []string{"partial"}, + [][2]string{ + {`{{ partial "header.html" . }}`, `<title>Hugo Rocks!</title>`}, + }, + ) + + ns.AddMethodMapping(ctx.getCached, + []string{"partialCached"}, + [][2]string{}, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/safe/init.go b/tpl/safe/init.go index fc47c66a7..94012a6ca 100644 --- a/tpl/safe/init.go +++ b/tpl/safe/init.go @@ -24,30 +24,57 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ "Bat&Man" | safeCSS | safeCSS }}`, `Bat&Man`}, - {`{{ "Bat&Man" | safeHTML | safeHTML }}`, `Bat&Man`}, - {`{{ "Bat&Man" | safeHTML }}`, `Bat&Man`}, - {`{{ "(1*2)" | safeJS | safeJS }}`, `(1*2)`}, - {`{{ "http://gohugo.io" | safeURL | safeURL }}`, `http://gohugo.io`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "safeCSS": ctx.CSS, - "safeHTML": ctx.HTML, - "safeHTMLAttr": ctx.HTMLAttr, - "safeJS": ctx.JS, - "safeJSStr": ctx.JSStr, - "safeURL": ctx.URL, - "sanitizeURL": ctx.SanitizeURL, - "sanitizeurl": ctx.SanitizeURL, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.CSS, + []string{"safeCSS"}, + [][2]string{ + {`{{ "Bat&Man" | safeCSS | safeCSS }}`, `Bat&Man`}, + }, + ) + + ns.AddMethodMapping(ctx.HTML, + []string{"safeHTML"}, + [][2]string{ + {`{{ "Bat&Man" | safeHTML | safeHTML }}`, `Bat&Man`}, + {`{{ "Bat&Man" | safeHTML }}`, `Bat&Man`}, + }, + ) + + ns.AddMethodMapping(ctx.HTMLAttr, + []string{"safeHTMLAttr"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.JS, + []string{"safeJS"}, + [][2]string{ + {`{{ "(1*2)" | safeJS | safeJS }}`, `(1*2)`}, + }, + ) + + ns.AddMethodMapping(ctx.JSStr, + []string{"safeJSStr"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.URL, + []string{"safeURL"}, + [][2]string{ + {`{{ "http://gohugo.io" | safeURL | safeURL }}`, `http://gohugo.io`}, + }, + ) + + ns.AddMethodMapping(ctx.SanitizeURL, + []string{"sanitizeURL", "sanitizeurl"}, + [][2]string{}, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/strings/init.go b/tpl/strings/init.go index 8e3dfdef2..9f33bd176 100644 --- a/tpl/strings/init.go +++ b/tpl/strings/init.go @@ -24,54 +24,118 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {`{{chomp "<p>Blockhead</p>\n" }}`, `<p>Blockhead</p>`}, - { - `{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`, - `[go]`}, - {`{{ hasPrefix "Hugo" "Hu" }}`, `true`}, - {`{{ hasPrefix "Hugo" "Fu" }}`, `false`}, - {`{{lower "BatMan"}}`, `batman`}, - { - `{{ replace "Batman and Robin" "Robin" "Catwoman" }}`, - `Batman and Catwoman`}, - { - `{{ "http://gohugo.io/docs" | replaceRE "^https?://([^/]+).*" "$1" }}`, - `gohugo.io`}, - {`{{slicestr "BatMan" 0 3}}`, `Bat`}, - {`{{slicestr "BatMan" 3}}`, `Man`}, - {`{{substr "BatMan" 0 -3}}`, `Bat`}, - {`{{substr "BatMan" 3 3}}`, `Man`}, - {`{{title "Bat man"}}`, `Bat Man`}, - {`{{ trim "++Batman--" "+-" }}`, `Batman`}, - {`{{ "this is a very long text" | truncate 10 " ..." }}`, `this is a ...`}, - {`{{ "With [Markdown](/markdown) inside." | markdownify | truncate 14 }}`, `With <a href="/markdown">Markdown …</a>`}, - {`{{upper "BatMan"}}`, `BATMAN`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "chomp": ctx.Chomp, - "countrunes": ctx.CountRunes, - "countwords": ctx.CountWords, - "findRE": ctx.FindRE, - "hasPrefix": ctx.HasPrefix, - "lower": ctx.ToLower, - "replace": ctx.Replace, - "replaceRE": ctx.ReplaceRE, - "slicestr": ctx.SliceString, - "split": ctx.Split, - "substr": ctx.Substr, - "title": ctx.Title, - "trim": ctx.Trim, - "truncate": ctx.Truncate, - "upper": ctx.ToUpper, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Chomp, + []string{"chomp"}, + [][2]string{ + {`{{chomp "<p>Blockhead</p>\n" }}`, `<p>Blockhead</p>`}, + }, + ) + + ns.AddMethodMapping(ctx.CountRunes, + []string{"countrunes"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.CountWords, + []string{"countwords"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.FindRE, + []string{"findRE"}, + [][2]string{ + { + `{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`, + `[go]`}, + }, + ) + + ns.AddMethodMapping(ctx.HasPrefix, + []string{"hasPrefix"}, + [][2]string{ + {`{{ hasPrefix "Hugo" "Hu" }}`, `true`}, + {`{{ hasPrefix "Hugo" "Fu" }}`, `false`}, + }, + ) + + ns.AddMethodMapping(ctx.ToLower, + []string{"lower"}, + [][2]string{ + {`{{lower "BatMan"}}`, `batman`}, + }, + ) + + ns.AddMethodMapping(ctx.Replace, + []string{"replace"}, + [][2]string{ + { + `{{ replace "Batman and Robin" "Robin" "Catwoman" }}`, + `Batman and Catwoman`}, + }, + ) + + ns.AddMethodMapping(ctx.ReplaceRE, + []string{"replaceRE"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.SliceString, + []string{"slicestr"}, + [][2]string{ + {`{{slicestr "BatMan" 0 3}}`, `Bat`}, + {`{{slicestr "BatMan" 3}}`, `Man`}, + }, + ) + + ns.AddMethodMapping(ctx.Split, + []string{"split"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.Substr, + []string{"substr"}, + [][2]string{ + {`{{substr "BatMan" 0 -3}}`, `Bat`}, + {`{{substr "BatMan" 3 3}}`, `Man`}, + }, + ) + + ns.AddMethodMapping(ctx.Trim, + []string{"trim"}, + [][2]string{ + {`{{ trim "++Batman--" "+-" }}`, `Batman`}, + }, + ) + + ns.AddMethodMapping(ctx.Title, + []string{"title"}, + [][2]string{ + {`{{title "Bat man"}}`, `Bat Man`}, + }, + ) + + ns.AddMethodMapping(ctx.Truncate, + []string{"truncate"}, + [][2]string{ + {`{{ "this is a very long text" | truncate 10 " ..." }}`, `this is a ...`}, + {`{{ "With [Markdown](/markdown) inside." | markdownify | truncate 14 }}`, `With <a href="/markdown">Markdown …</a>`}, + }, + ) + + ns.AddMethodMapping(ctx.ToUpper, + []string{"upper"}, + [][2]string{ + {`{{upper "BatMan"}}`, `BATMAN`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/time/init.go b/tpl/time/init.go index d91c1376f..33f8a7dbb 100644 --- a/tpl/time/init.go +++ b/tpl/time/init.go @@ -24,22 +24,32 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New() - examples := [][2]string{ - {`{{ (time "2015-01-21").Year }}`, `2015`}, - {`dateFormat: {{ dateFormat "Monday, Jan 2, 2006" "2015-01-21" }}`, `dateFormat: Wednesday, Jan 21, 2015`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "dateFormat": ctx.Format, - "now": ctx.Now, - "time": ctx.AsTime, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Format, + []string{"dateFormat"}, + [][2]string{ + {`dateFormat: {{ dateFormat "Monday, Jan 2, 2006" "2015-01-21" }}`, `dateFormat: Wednesday, Jan 21, 2015`}, + }, + ) + + ns.AddMethodMapping(ctx.Now, + []string{"now"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.AsTime, + []string{"asTime"}, // TODO(bep) handle duplicate + [][2]string{ + {`{{ (asTime "2015-01-21").Year }}`, `2015`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/tplimpl/template_funcs.go b/tpl/tplimpl/template_funcs.go index 089463a1e..938f4531c 100644 --- a/tpl/tplimpl/template_funcs.go +++ b/tpl/tplimpl/template_funcs.go @@ -51,8 +51,14 @@ func (t *templateFuncster) initFuncMap() { panic(ns.Name + " is a duplicate template func") } funcMap[ns.Name] = ns.Context - for k, v := range ns.Aliases { - funcMap[k] = v + for _, mm := range ns.MethodMappings { + for _, alias := range mm.Aliases { + if _, exists := funcMap[alias]; exists { + panic(alias + " is a duplicate template func") + } + funcMap[alias] = mm.Method + } + } } diff --git a/tpl/tplimpl/template_funcs_test.go b/tpl/tplimpl/template_funcs_test.go index b0a6e87b7..97685f96e 100644 --- a/tpl/tplimpl/template_funcs_test.go +++ b/tpl/tplimpl/template_funcs_test.go @@ -87,19 +87,21 @@ func TestTemplateFuncsExamples(t *testing.T) { for _, nsf := range internal.TemplateFuncsNamespaceRegistry { ns := nsf(d) - for i, example := range ns.Examples { - in, expected := example[0], example[1] - d.WithTemplate = func(templ tpl.TemplateHandler) error { - require.NoError(t, templ.AddTemplate("test", in)) - require.NoError(t, templ.AddTemplate("partials/header.html", "<title>Hugo Rocks!</title>")) - return nil - } - require.NoError(t, d.LoadResources()) - - var b bytes.Buffer - require.NoError(t, d.Tmpl.Lookup("test").Execute(&b, &data)) - if b.String() != expected { - t.Fatalf("%s[%d]: got %q expected %q", ns.Name, i, b.String(), expected) + for _, mm := range ns.MethodMappings { + for i, example := range mm.Examples { + in, expected := example[0], example[1] + d.WithTemplate = func(templ tpl.TemplateHandler) error { + require.NoError(t, templ.AddTemplate("test", in)) + require.NoError(t, templ.AddTemplate("partials/header.html", "<title>Hugo Rocks!</title>")) + return nil + } + require.NoError(t, d.LoadResources()) + + var b bytes.Buffer + require.NoError(t, d.Tmpl.Lookup("test").Execute(&b, &data)) + if b.String() != expected { + t.Fatalf("%s[%d]: got %q expected %q", ns.Name, i, b.String(), expected) + } } } } diff --git a/tpl/transform/init.go b/tpl/transform/init.go index 98994c0e6..3483d1306 100644 --- a/tpl/transform/init.go +++ b/tpl/transform/init.go @@ -24,47 +24,72 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {`{{ "I :heart: Hugo" | emojify }}`, `I ❤️ Hugo`}, - {`{{ .Title | markdownify}}`, `<strong>BatMan</strong>`}, - {`{{ plainify "Hello <strong>world</strong>, gophers!" }}`, `Hello world, gophers!`}, - { - `htmlEscape 1: {{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | safeHTML}}`, - `htmlEscape 1: Cathal Garvey & The Sunshine Band <[email protected]>`}, - { - `htmlEscape 2: {{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>"}}`, - `htmlEscape 2: Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`}, - { - `htmlUnescape 1: {{htmlUnescape "Cathal Garvey & The Sunshine Band <[email protected]>" | safeHTML}}`, - `htmlUnescape 1: Cathal Garvey & The Sunshine Band <[email protected]>`}, - { - `htmlUnescape 2: {{"Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | htmlUnescape | htmlUnescape | safeHTML}}`, - `htmlUnescape 2: Cathal Garvey & The Sunshine Band <[email protected]>`}, - { - `htmlUnescape 3: {{"Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | htmlUnescape | htmlUnescape }}`, - `htmlUnescape 3: Cathal Garvey & The Sunshine Band <[email protected]>`}, - { - `htmlUnescape 4: {{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | htmlUnescape | safeHTML }}`, - `htmlUnescape 4: Cathal Garvey & The Sunshine Band <[email protected]>`}, - { - `htmlUnescape 5: {{ htmlUnescape "Cathal Garvey & The Sunshine Band <[email protected]>" | htmlEscape | safeHTML }}`, - `htmlUnescape 5: Cathal Garvey & The Sunshine Band <[email protected]>`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "emojify": ctx.Emojify, - "highlight": ctx.Highlight, - "htmlEscape": ctx.HTMLEscape, - "htmlUnescape": ctx.HTMLUnescape, - "markdownify": ctx.Markdownify, - "plainify": ctx.Plainify, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.Emojify, + []string{"emojify"}, + [][2]string{ + {`{{ "I :heart: Hugo" | emojify }}`, `I ❤️ Hugo`}, + }, + ) + + ns.AddMethodMapping(ctx.Highlight, + []string{"highlight"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.HTMLEscape, + []string{"htmlEscape"}, + [][2]string{ + { + `{{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | safeHTML}}`, + `Cathal Garvey & The Sunshine Band <[email protected]>`}, + { + `{{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>"}}`, + `Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;`}, + { + `{{ htmlEscape "Cathal Garvey & The Sunshine Band <[email protected]>" | htmlUnescape | safeHTML }}`, + `Cathal Garvey & The Sunshine Band <[email protected]>`}, + }, + ) + + ns.AddMethodMapping(ctx.HTMLUnescape, + []string{"htmlUnescape"}, + [][2]string{ + { + `{{ htmlUnescape "Cathal Garvey & The Sunshine Band <[email protected]>" | safeHTML}}`, + `Cathal Garvey & The Sunshine Band <[email protected]>`}, + { + `{{"Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | htmlUnescape | htmlUnescape | safeHTML}}`, + `Cathal Garvey & The Sunshine Band <[email protected]>`}, + { + `{{"Cathal Garvey &amp; The Sunshine Band &lt;[email protected]&gt;" | htmlUnescape | htmlUnescape }}`, + `Cathal Garvey & The Sunshine Band <[email protected]>`}, + { + `{{ htmlUnescape "Cathal Garvey & The Sunshine Band <[email protected]>" | htmlEscape | safeHTML }}`, + `Cathal Garvey & The Sunshine Band <[email protected]>`}, + }, + ) + + ns.AddMethodMapping(ctx.Markdownify, + []string{"markdownify"}, + [][2]string{ + {`{{ .Title | markdownify}}`, `<strong>BatMan</strong>`}, + }, + ) + + ns.AddMethodMapping(ctx.Plainify, + []string{"plainify"}, + [][2]string{ + {`{{ plainify "Hello <strong>world</strong>, gophers!" }}`, `Hello world, gophers!`}, + }, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) diff --git a/tpl/urls/init.go b/tpl/urls/init.go index fb9b00a27..e32807f32 100644 --- a/tpl/urls/init.go +++ b/tpl/urls/init.go @@ -24,33 +24,43 @@ func init() { f := func(d *deps.Deps) *internal.TemplateFuncsNamespace { ctx := New(d) - examples := [][2]string{ - {`{{ "index.html" | absLangURL }}`, `http://mysite.com/hugo/en/index.html`}, - {`{{ "http://gohugo.io/" | absURL }}`, `http://gohugo.io/`}, - {`{{ "mystyle.css" | absURL }}`, `http://mysite.com/hugo/mystyle.css`}, - {`{{ 42 | absURL }}`, `http://mysite.com/hugo/42`}, - {`{{ "index.html" | relLangURL }}`, `/hugo/en/index.html`}, - {`{{ "http://gohugo.io/" | relURL }}`, `http://gohugo.io/`}, - {`{{ "mystyle.css" | relURL }}`, `/hugo/mystyle.css`}, - {`{{ mul 2 21 | relURL }}`, `/hugo/42`}, - {`{{ "Bat Man" | urlize }}`, `bat-man`}, - } - - return &internal.TemplateFuncsNamespace{ + ns := &internal.TemplateFuncsNamespace{ Name: name, Context: func() interface{} { return ctx }, - Aliases: map[string]interface{}{ - "absURL": ctx.AbsURL, - "absLangURL": ctx.AbsLangURL, - "ref": ctx.Ref, - "relURL": ctx.RelURL, - "relLangURL": ctx.RelLangURL, - "relref": ctx.RelRef, - "urlize": ctx.URLize, - }, - Examples: examples, } + ns.AddMethodMapping(ctx.AbsURL, + []string{"absURL"}, + [][2]string{}, + ) + + ns.AddMethodMapping(ctx.AbsLangURL, + []string{"absLangURL"}, + [][2]string{}, + ) + ns.AddMethodMapping(ctx.Ref, + []string{"ref"}, + [][2]string{}, + ) + ns.AddMethodMapping(ctx.RelURL, + []string{"relURL"}, + [][2]string{}, + ) + ns.AddMethodMapping(ctx.RelLangURL, + []string{"relLangURL"}, + [][2]string{}, + ) + ns.AddMethodMapping(ctx.RelRef, + []string{"relref"}, + [][2]string{}, + ) + ns.AddMethodMapping(ctx.URLize, + []string{"urlize"}, + [][2]string{}, + ) + + return ns + } internal.AddTemplateFuncsNamespace(f) |