mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
tpl: Add docshelper for template funcs
And fix some other minor related issues. Updates #3418
This commit is contained in:
parent
e2b067f050
commit
690b0f8ff5
25 changed files with 2064 additions and 347 deletions
1223
docs/data/docs.json
1223
docs/data/docs.json
File diff suppressed because it is too large
Load diff
41
tpl/cast/docshelper.go
Normal file
41
tpl/cast/docshelper.go
Normal file
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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...)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
33
tpl/internal/templatefuncRegistry_test.go
Normal file
33
tpl/internal/templatefuncRegistry_test.go
Normal file
|
@ -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))
|
||||
}
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <cathal@foo.bar>" | safeHTML}}`,
|
||||
`htmlEscape 1: Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`htmlEscape 2: {{ htmlEscape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>"}}`,
|
||||
`htmlEscape 2: Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;`},
|
||||
{
|
||||
`htmlUnescape 1: {{htmlUnescape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" | safeHTML}}`,
|
||||
`htmlUnescape 1: Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`htmlUnescape 2: {{"Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;" | htmlUnescape | htmlUnescape | safeHTML}}`,
|
||||
`htmlUnescape 2: Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`htmlUnescape 3: {{"Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;" | htmlUnescape | htmlUnescape }}`,
|
||||
`htmlUnescape 3: Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`htmlUnescape 4: {{ htmlEscape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" | htmlUnescape | safeHTML }}`,
|
||||
`htmlUnescape 4: Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`htmlUnescape 5: {{ htmlUnescape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" | htmlEscape | safeHTML }}`,
|
||||
`htmlUnescape 5: Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
}
|
||||
|
||||
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 <cathal@foo.bar>" | safeHTML}}`,
|
||||
`Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`{{ htmlEscape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>"}}`,
|
||||
`Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;`},
|
||||
{
|
||||
`{{ htmlEscape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" | htmlUnescape | safeHTML }}`,
|
||||
`Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.HTMLUnescape,
|
||||
[]string{"htmlUnescape"},
|
||||
[][2]string{
|
||||
{
|
||||
`{{ htmlUnescape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" | safeHTML}}`,
|
||||
`Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`{{"Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;" | htmlUnescape | htmlUnescape | safeHTML}}`,
|
||||
`Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`{{"Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;" | htmlUnescape | htmlUnescape }}`,
|
||||
`Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
{
|
||||
`{{ htmlUnescape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" | htmlEscape | safeHTML }}`,
|
||||
`Cathal Garvey & The Sunshine Band <cathal@foo.bar>`},
|
||||
},
|
||||
)
|
||||
|
||||
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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue