ref: 4ea4359ac17a3b5304fb0d73773f99a07975ee1e
parent: bc06135c96aa4db6fe36a4fc4f19a18fa1cb8935
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Sun Jan 8 11:54:05 EST 2017
hugolib: Avoid double-encoding of paginator URLs Fixes #2177
--- a/hugolib/hugo_sites_build_test.go
+++ b/hugolib/hugo_sites_build_test.go
@@ -171,7 +171,7 @@
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)))}
}
--- a/hugolib/pagination.go
+++ b/hugolib/pagination.go
@@ -20,7 +20,6 @@
"math"
"path"
"reflect"
- "strings"
"github.com/spf13/cast"
"github.com/spf13/hugo/helpers"
@@ -280,7 +279,7 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 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)
--- a/hugolib/pagination_test.go
+++ b/hugolib/pagination_test.go
@@ -200,7 +200,6 @@
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))
@@ -273,6 +272,41 @@
for _, useViper := range []bool{false, true} {doTestPaginate(t, useViper)
}
+}
+
+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) {--
⑨