From 4ea4359ac17a3b5304fb0d73773f99a07975ee1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sun, 8 Jan 2017 16:54:05 +0100 Subject: [PATCH] hugolib: Avoid double-encoding of paginator URLs Fixes #2177 --- hugolib/hugo_sites_build_test.go | 2 +- hugolib/pagination.go | 40 ++++++++++++++++---------------- hugolib/pagination_test.go | 36 +++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/hugolib/hugo_sites_build_test.go b/hugolib/hugo_sites_build_test.go index cdf56f182..a8fc9a58f 100644 --- a/hugolib/hugo_sites_build_test.go +++ b/hugolib/hugo_sites_build_test.go @@ -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))) } } diff --git a/hugolib/pagination.go b/hugolib/pagination.go index 93fe50078..14a081131 100644 --- a/hugolib/pagination.go +++ b/hugolib/pagination.go @@ -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) diff --git a/hugolib/pagination_test.go b/hugolib/pagination_test.go index 125840c66..9bc8ffea4 100644 --- a/hugolib/pagination_test.go +++ b/hugolib/pagination_test.go @@ -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"), "{{.Content}}") + writeSource(t, filepath.Join("layouts", "_default", "list.html"), + ` + +Count: {{ .Paginator.TotalNumberOfElements }} +Pages: {{ .Paginator.TotalPages }} +{{ range .Paginator.Pagers -}} + {{ .PageNumber }}: {{ .URL }} +{{ end }} +`) + + 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 {