tpl: Allow 'Querify' to take lone slice/interface argument - hugo - [fork] hugo port for 9front
 (HTM) git clone git@git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c46fc838a9320adfc6532b1b543e903c48b3b4cb
 (DIR) parent 504c78da4b5020e1fd13a1195ad38a9e85f8289a
 (HTM) Author: Ujjwal Goyal <importujjwal@gmail.com>
       Date:   Sun,  7 Mar 2021 00:08:10 +0530
       
       tpl: Allow 'Querify' to take lone slice/interface argument
       
       Querify can now take a lone string/interface slice (with string
       keys) as a parameter, or multiple string parameters, to build
       URL queries.
       
       Querify earlier used 'Dictionary' to add key/value pairs to a
       map to build URL queries. Changed to dynamically generate ordered
       key/value pairs. Cannot take string slice as key (earlier
       possible due to Dictionary).
       
       Added tests and benchmarks for querify.
       
       Closes #6735
       
       Diffstat:
         M tpl/collections/collections.go      |      36 ++++++++++++++++++++++++++-----
         M tpl/collections/collections_test.go |      33 +++++++++++++++++++++++++++++++
         M tpl/collections/init.go             |       4 ++++
       
       3 files changed, 68 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git 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")
       +                }
       +        }
       +
       +        if len(params)%2 != 0 {
       +                return "", errors.New("invalid query")
                }
        
       -        for name, value := range vals {
       -                qs.Add(name, fmt.Sprintf("%v", value))
       +        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
 (DIR) diff --git 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)
 (DIR) diff --git a/tpl/collections/init.go b/tpl/collections/init.go
       @@ -122,6 +122,10 @@ func init() {
                                                `<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a>`,
                                                `<a href="https://www.google.com?page=3&amp;q=test">Search</a>`,
                                        },
       +                                {
       +                                        `{{ slice "foo" 1 "bar" 2 | querify | safeHTML }}`,
       +                                        `bar=2&foo=1`,
       +                                },
                                },
                        )