hugolib: Avoid double-encoding of paginator URLs
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 8 Jan 2017 15:54:05 +0000 (16:54 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 8 Jan 2017 16:13:46 +0000 (17:13 +0100)
Fixes #2177

hugolib/hugo_sites_build_test.go
hugolib/pagination.go
hugolib/pagination_test.go

index cdf56f18229004fca67ab079c76f31efe4eb618e..a8fc9a58f7ce55ca6e8d660a891b264381407301 100644 (file)
@@ -171,7 +171,7 @@ func assertFileContent(t *testing.T, filename string, defaultInSubDir bool, matc
        content := readDestination(t, filename)
        for _, match := range matches {
                match = replaceDefaultContentLanguageValue(match, defaultInSubDir)
-               require.True(t, strings.Contains(content, match), fmt.Sprintf("File no match for\n%q in\n%q:\n%s", match, filename, content))
+               require.True(t, strings.Contains(content, match), fmt.Sprintf("File no match for\n%q in\n%q:\n%s", strings.Replace(match, "%", "%%", -1), filename, strings.Replace(content, "%", "%%", -1)))
        }
 }
 
index 93fe50078f095ecb000949f3a400a72556582ff8..14a081131c6d0d646c8f8e981bfcd6de564b59cf 100644 (file)
@@ -20,7 +20,6 @@ import (
        "math"
        "path"
        "reflect"
-       "strings"
 
        "github.com/spf13/cast"
        "github.com/spf13/hugo/helpers"
@@ -280,7 +279,7 @@ func (p *Page) Paginator(options ...interface{}) (*Pager, error) {
                        return
                }
 
-               pagers, err := paginatePages(p.Data["Pages"], pagerSize, p.URL())
+               pagers, err := paginatePages(p.Data["Pages"], pagerSize, p.sections...)
 
                if err != nil {
                        initError = err
@@ -306,9 +305,9 @@ func (p *Page) Paginator(options ...interface{}) (*Pager, error) {
 // Paginate gets this Node's paginator if it's already created.
 // If it's not, one will be created with the qiven sequence.
 // Note that repeated calls will return the same result, even if the sequence is different.
-func (n *Page) Paginate(seq interface{}, options ...interface{}) (*Pager, error) {
-       if !n.IsNode() {
-               return nil, fmt.Errorf("Paginators not supported for pages of type %q (%q)", n.Kind, n.Title)
+func (p *Page) Paginate(seq interface{}, options ...interface{}) (*Pager, error) {
+       if !p.IsNode() {
+               return nil, fmt.Errorf("Paginators not supported for pages of type %q (%q)", p.Kind, p.Title)
        }
 
        pagerSize, err := resolvePagerSize(options...)
@@ -319,11 +318,11 @@ func (n *Page) Paginate(seq interface{}, options ...interface{}) (*Pager, error)
 
        var initError error
 
-       n.paginatorInit.Do(func() {
-               if n.paginator != nil {
+       p.paginatorInit.Do(func() {
+               if p.paginator != nil {
                        return
                }
-               pagers, err := paginatePages(seq, pagerSize, n.URL())
+               pagers, err := paginatePages(seq, pagerSize, p.sections...)
 
                if err != nil {
                        initError = err
@@ -331,10 +330,10 @@ func (n *Page) Paginate(seq interface{}, options ...interface{}) (*Pager, error)
 
                if len(pagers) > 0 {
                        // the rest of the nodes will be created later
-                       n.paginator = pagers[0]
-                       n.paginator.source = seq
-                       n.paginator.options = options
-                       n.Site.addToPaginationPageCount(uint64(n.paginator.TotalPages()))
+                       p.paginator = pagers[0]
+                       p.paginator.source = seq
+                       p.paginator.options = options
+                       p.Site.addToPaginationPageCount(uint64(p.paginator.TotalPages()))
                }
 
        })
@@ -343,15 +342,15 @@ func (n *Page) Paginate(seq interface{}, options ...interface{}) (*Pager, error)
                return nil, initError
        }
 
-       if n.paginator.source == "paginator" {
+       if p.paginator.source == "paginator" {
                return nil, errors.New("a Paginator was previously built for this Node without filters; look for earlier .Paginator usage")
        }
 
-       if !reflect.DeepEqual(options, n.paginator.options) || !probablyEqualPageLists(n.paginator.source, seq) {
+       if !reflect.DeepEqual(options, p.paginator.options) || !probablyEqualPageLists(p.paginator.source, seq) {
                return nil, errors.New("invoked multiple times with different arguments")
        }
 
-       return n.paginator, nil
+       return p.paginator, nil
 }
 
 func resolvePagerSize(options ...interface{}) (int, error) {
@@ -372,14 +371,13 @@ func resolvePagerSize(options ...interface{}) (int, error) {
        return pas, nil
 }
 
-func paginatePages(seq interface{}, pagerSize int, section string) (pagers, error) {
+func paginatePages(seq interface{}, pagerSize int, sections ...string) (pagers, error) {
 
        if pagerSize <= 0 {
                return nil, errors.New("'paginate' configuration setting must be positive to paginate")
        }
 
-       section = strings.TrimSuffix(section, ".html")
-       urlFactory := newPaginationURLFactory(section)
+       urlFactory := newPaginationURLFactory(sections...)
 
        var paginator *paginator
 
@@ -509,12 +507,14 @@ func newPaginator(elements []paginatedElement, total, size int, urlFactory pagin
 func newPaginationURLFactory(pathElements ...string) paginationURLFactory {
        pathSpec := helpers.CurrentPathSpec()
 
+       basePath := path.Join(pathElements...)
+
        return func(page int) string {
                var rel string
                if page == 1 {
-                       rel = fmt.Sprintf("/%s/", path.Join(pathElements...))
+                       rel = fmt.Sprintf("/%s/", basePath)
                } else {
-                       rel = fmt.Sprintf("/%s/%s/%d/", path.Join(pathElements...), pathSpec.PaginatePath(), page)
+                       rel = fmt.Sprintf("/%s/%s/%d/", basePath, pathSpec.PaginatePath(), page)
                }
 
                return pathSpec.URLizeAndPrep(rel)
index 125840c66ca2fd74af15e1e8de50e088e43826bd..9bc8ffea4c1df3427c707a4754ac3e7d26809579 100644 (file)
@@ -200,7 +200,6 @@ func TestPaginationURLFactory(t *testing.T) {
        unicode := newPaginationURLFactory("новости проекта")
        fooBar := newPaginationURLFactory("foo", "bar")
 
-       assert.Equal(t, "/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0/", unicode(1))
        assert.Equal(t, "/foo/bar/", fooBar(1))
        assert.Equal(t, "/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0/zoo/4/", unicode(4))
        assert.Equal(t, "/foo/bar/zoo/12345/", fooBar(12345))
@@ -275,6 +274,41 @@ func TestPaginate(t *testing.T) {
        }
 }
 
+func TestPaginatorURL(t *testing.T) {
+
+       testCommonResetState()
+       viper.Set("paginate", 2)
+       viper.Set("paginatePath", "testing")
+
+       for i := 0; i < 10; i++ {
+               // Issue #2177, do not double encode URLs
+               writeSource(t, filepath.Join("content", "阅读", fmt.Sprintf("page%d.md", (i+1))),
+                       fmt.Sprintf(`---
+title: Page%d
+---
+Conten%d
+`, (i+1), i+1))
+
+       }
+       writeSource(t, filepath.Join("layouts", "_default", "single.html"), "<html><body>{{.Content}}</body></html>")
+       writeSource(t, filepath.Join("layouts", "_default", "list.html"),
+               `
+<html><body>
+Count: {{ .Paginator.TotalNumberOfElements }}
+Pages: {{ .Paginator.TotalPages }}
+{{ range .Paginator.Pagers -}}
+ {{ .PageNumber }}: {{ .URL }} 
+{{ end }}
+</body></html>`)
+
+       if err := buildAndRenderSite(NewSiteDefaultLang()); err != nil {
+               t.Fatalf("Failed to build site: %s", err)
+       }
+
+       assertFileContent(t, filepath.Join("public", "阅读", "testing", "2", "index.html"), false, "2: /%E9%98%85%E8%AF%BB/testing/2/")
+
+}
+
 func doTestPaginate(t *testing.T, useViper bool) {
        pagerSize := 5
        if useViper {