Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions pkg/template/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func SplitLines(o interface{}) ([]string, error) {

// FromJSON decode the input JSON encoded as string or byte slice into a map.
func FromJSON(o interface{}) (interface{}, error) {
ret := map[string]interface{}{}
var ret interface{}
switch o := o.(type) {
case string:
err := json.Unmarshal([]byte(o), &ret)
Expand Down Expand Up @@ -136,11 +136,37 @@ func (t *Template) DefaultFuncs() map[string]interface{} {
return make([]struct{}, c)
},

"var": func(name, doc string, v ...interface{}) interface{} {
"def": func(name string, args ...interface{}) (string, error) {
if _, has := t.defaults[name]; has {
// not sure if this is good, but should complain loudly
return "", fmt.Errorf("already defined: %v", name)
}
var doc string
var value interface{}
switch len(args) {
case 1:
// just value, no docs
value = args[0]
case 2:
// docs and value
doc = fmt.Sprintf("%v", args[0])
value = args[1]
}
t.defaults[name] = defaultValue{
Name: name,
Value: value,
Doc: doc,
}
return "", nil
},

"ref": func(name string) interface{} {
if found, has := t.binds[name]; has {
return found
} else if v, has := t.defaults[name]; has {
return v.Value
}
return v // default
return nil
},

"global": func(name string, v interface{}) interface{} {
Expand Down
8 changes: 8 additions & 0 deletions pkg/template/funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ func TestQueryObjectEncodeDecode(t *testing.T) {
require.NoError(t, err)

require.Equal(t, decoded, decoded2)

decoded, err = FromJSON("[]")
require.NoError(t, err)
require.Equal(t, []interface{}{}, decoded)

decoded, err = FromJSON(`{"foo":"bar"}`)
require.NoError(t, err)
require.Equal(t, map[string]interface{}{"foo": "bar"}, decoded)
}

func TestQueryObject(t *testing.T) {
Expand Down
30 changes: 19 additions & 11 deletions pkg/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,23 @@ type Options struct {
SocketDir string
}

type defaultValue struct {
Name string
Value interface{}
Doc string
}

// Template is the templating engine
type Template struct {
options Options

url string
body []byte
parsed *template.Template
funcs map[string]interface{}
binds map[string]interface{}
lock sync.Mutex
url string
body []byte
parsed *template.Template
funcs map[string]interface{}
binds map[string]interface{}
defaults map[string]defaultValue
lock sync.Mutex
}

// NewTemplate fetches the content at the url and returns a template. If the string begins
Expand Down Expand Up @@ -84,11 +91,12 @@ func NewTemplateFromBytes(buff []byte, contextURL string, opt Options) (*Templat
}

return &Template{
options: opt,
url: contextURL,
body: buff,
funcs: map[string]interface{}{},
binds: map[string]interface{}{},
options: opt,
url: contextURL,
body: buff,
funcs: map[string]interface{}{},
binds: map[string]interface{}{},
defaults: map[string]defaultValue{},
}, nil
}

Expand Down
17 changes: 15 additions & 2 deletions pkg/template/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,15 @@ func TestVarAndGlobal(t *testing.T) {
str := `{{ q "locations[?state == 'WA'].name | sort(@) | {WashingtonCities: join(', ', @)}" . | global "washington-cities"}}

{{/* The query above is exported and referenced somewhere else */}}
{{ from_json "[\"SF\",\"LA\"]" | def "california-cities" "Default value for California cities" }}
{{ from_json "{\"SF\":\"94109\",\"LA\":\"90210\"}" | def "zip-codes" "Default value for zip codes" }}

{
"test" : "hello",
"val" : true,
"result" : {{var "washington-cities" "A json with washington cities" | to_json}}
"result" : {{ref "washington-cities" | to_json}},
"california" : {{ ref "california-cities" | to_json}},
"sf_zip" : {{ ref "zip-codes" | q "SF" | to_json }}
}
`

Expand All @@ -59,12 +64,20 @@ func TestVarAndGlobal(t *testing.T) {
expected := `





{
"test" : "hello",
"val" : true,
"result" : {
"WashingtonCities": "Bellevue, Olympia, Seattle"
}
},
"california" : [
"SF",
"LA"
],
"sf_zip" : "94109"
}
`
require.Equal(t, expected, view)
Expand Down