mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-26 22:04:32 +02:00
tpl: Add docshelper for template funcs
And fix some other minor related issues. Updates #3418
This commit is contained in:
@@ -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,
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user