diff --git a/tpl/collections/collections.go b/tpl/collections/collections.go
index 3521f9cd5..669e386f8 100644
--- a/tpl/collections/collections.go
+++ b/tpl/collections/collections.go
@@ -424,13 +424,39 @@ func (ns *Namespace) Last(limit interface{}, seq interface{}) (interface{}, erro
// Querify encodes the given parameters in URL-encoded form ("bar=baz&foo=quux") sorted by key.
func (ns *Namespace) Querify(params ...interface{}) (string, error) {
qs := url.Values{}
- vals, err := ns.Dictionary(params...)
- if err != nil {
- return "", errors.New("querify keys must be strings")
+
+ if len(params) == 1 {
+ switch v := params[0].(type) {
+ case []string:
+ if len(v)%2 != 0 {
+ return "", errors.New("invalid query")
+ }
+
+ for i := 0; i < len(v); i += 2 {
+ qs.Add(v[i], v[i+1])
+ }
+
+ return qs.Encode(), nil
+
+ case []interface{}:
+ params = v
+
+ default:
+ return "", errors.New("query keys must be strings")
+ }
}
- for name, value := range vals {
- qs.Add(name, fmt.Sprintf("%v", value))
+ if len(params)%2 != 0 {
+ return "", errors.New("invalid query")
+ }
+
+ for i := 0; i < len(params); i += 2 {
+ switch v := params[i].(type) {
+ case string:
+ qs.Add(v, fmt.Sprintf("%v", params[i+1]))
+ default:
+ return "", errors.New("query keys must be strings")
+ }
}
return qs.Encode(), nil
diff --git a/tpl/collections/collections_test.go b/tpl/collections/collections_test.go
index a9bf9a09b..1e0569751 100644
--- a/tpl/collections/collections_test.go
+++ b/tpl/collections/collections_test.go
@@ -564,9 +564,16 @@ func TestQuerify(t *testing.T) {
}{
{[]interface{}{"a", "b"}, "a=b"},
{[]interface{}{"a", "b", "c", "d", "f", " &"}, `a=b&c=d&f=+%26`},
+ {[]interface{}{[]string{"a", "b"}}, "a=b"},
+ {[]interface{}{[]string{"a", "b", "c", "d", "f", " &"}}, `a=b&c=d&f=+%26`},
+ {[]interface{}{[]interface{}{"x", "y"}}, `x=y`},
+ {[]interface{}{[]interface{}{"x", 5}}, `x=5`},
// errors
{[]interface{}{5, "b"}, false},
{[]interface{}{"a", "b", "c"}, false},
+ {[]interface{}{[]string{"a", "b", "c"}}, false},
+ {[]interface{}{[]string{"a", "b"}, "c"}, false},
+ {[]interface{}{[]interface{}{"c", "d", "e"}}, false},
} {
errMsg := qt.Commentf("[%d] %v", i, test.params)
@@ -582,6 +589,32 @@ func TestQuerify(t *testing.T) {
}
}
+func BenchmarkQuerify(b *testing.B) {
+ ns := New(&deps.Deps{})
+ params := []interface{}{"a", "b", "c", "d", "f", " &"}
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := ns.Querify(params...)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+func BenchmarkQuerifySlice(b *testing.B) {
+ ns := New(&deps.Deps{})
+ params := []string{"a", "b", "c", "d", "f", " &"}
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := ns.Querify(params)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
func TestSeq(t *testing.T) {
t.Parallel()
c := qt.New(t)
diff --git a/tpl/collections/init.go b/tpl/collections/init.go
index 1e6412610..4126b4410 100644
--- a/tpl/collections/init.go
+++ b/tpl/collections/init.go
@@ -122,6 +122,10 @@ func init() {
`Search`,
`Search`,
},
+ {
+ `{{ slice "foo" 1 "bar" 2 | querify | safeHTML }}`,
+ `bar=2&foo=1`,
+ },
},
)