ref: 37445bc6aa6273a819724eb25f24f08265d21d4b
parent: 407e80a9abbb3b22397d1ed6c62ce7cefcdd312a
author: bep <bjorn.erik.pedersen@gmail.com>
date: Sat Dec 27 09:11:19 EST 2014
Add pagination support for home page, sections and taxonomies
Two new configuration properties, `Paginate` (default `0`) and `PaginatePath` (default `page`) are added.
Setting `paginate` to a positive value will split the list pages for the home page, sections and taxonomies into chunks of size of the `paginate` property.
A `.Paginator` is provided to help building a pager menu.
There are two ways to configure a `.Paginator`:
1. The simplest way is just to call `.Paginator.Pages` from a template. It will contain the pages for "that page" (`.Data.Pages` will (like today) contain all the pages).
2. Select a sub-set of the pages with the available template functions and pass the slice to `.Paginate` : `{{ range (.Paginate (where .Data.Pages "Type" "post")).Pages }}`
**NOTE:** For a given Node, it's one of the options above. It's perfectly legitimate to iterate over the same pager more than once, but it's static and cannot change.
The `.Paginator` contains enough information to build a full-blown paginator interface.
The pages are built on the form (note: BLANK means no value, i.e. home page):
```
[SECTION/TAXONOMY/BLANK]/index.html
[SECTION/TAXONOMY/BLANK]/page/1/index.html => redirect to [SECTION/TAXONOMY/BLANK]/index.html
[SECTION/TAXONOMY/BLANK]/page/2/index.html
....
```
Fixes #96
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -136,6 +136,8 @@
viper.SetDefault("FootnoteAnchorPrefix", "") viper.SetDefault("FootnoteReturnLinkContents", "") viper.SetDefault("NewContentEditor", "")+ viper.SetDefault("Paginate", 0)+ viper.SetDefault("PaginatePath", "page") viper.SetDefault("Blackfriday", new(helpers.Blackfriday)) if hugoCmdV.PersistentFlags().Lookup("buildDrafts").Changed {--- a/helpers/url.go
+++ b/helpers/url.go
@@ -16,6 +16,7 @@
import (
"fmt"
"github.com/PuerkitoBio/purell"
+ "github.com/spf13/viper"
"net/url"
"path"
"strings"
@@ -95,6 +96,10 @@
newPath += "/"
}
return newPath
+}
+
+func UrlizeAndPrep(in string) string {+ return UrlPrep(viper.GetBool("UglyUrls"), Urlize(in))}
func UrlPrep(ugly bool, in string) string {--- a/hugolib/node.go
+++ b/hugolib/node.go
@@ -15,6 +15,7 @@
import (
"html/template"
+ "sync"
"time"
)
@@ -30,6 +31,8 @@
Date time.Time
Sitemap Sitemap
UrlPath
+ paginator *pager
+ paginatorInit sync.Once
}
func (n *Node) Now() time.Time {--- /dev/null
+++ b/hugolib/pagination.go
@@ -1,0 +1,269 @@
+// Copyright © 2013-14 Steve Francia <spf@spf13.com>.
+//
+// Licensed under the Simple Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://opensource.org/licenses/Simple-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package hugolib
+
+import (
+ "errors"
+ "fmt"
+ "github.com/spf13/hugo/helpers"
+ "github.com/spf13/viper"
+ "html/template"
+ "math"
+ "path"
+)
+
+type pager struct {+ number int
+ *paginator
+}
+
+type pagers []*pager
+
+type paginator struct {+ paginatedPages []Pages
+ pagers
+ paginationUrlFactory
+ total int
+ size int
+}
+
+type paginationUrlFactory func(int) string
+
+// PageNumber returns the current page's number in the pager sequence.
+func (p *pager) PageNumber() int {+ return p.number
+}
+
+// Url returns the url to the current page.
+func (p *pager) Url() template.HTML {+ return template.HTML(p.paginationUrlFactory(p.PageNumber()))
+}
+
+// Pages returns the elements on this page.
+func (p *pager) Pages() Pages {+ return p.paginatedPages[p.PageNumber()-1]
+}
+
+// NumberOfElements gets the number of elements on this page.
+func (p *pager) NumberOfElements() int {+ return len(p.Pages())
+}
+
+// HasPrev tests whether there are page(s) before the current.
+func (p *pager) HasPrev() bool {+ return p.PageNumber() > 1
+}
+
+// Prev returns the pager for the previous page.
+func (p *pager) Prev() *pager {+ if !p.HasPrev() {+ return nil
+ }
+ return p.pagers[p.PageNumber()-2]
+}
+
+// HasNext tests whether there are page(s) after the current.
+func (p *pager) HasNext() bool {+ return p.PageNumber() < len(p.paginatedPages)
+}
+
+// Next returns the pager for the next page.
+func (p *pager) Next() *pager {+ if !p.HasNext() {+ return nil
+ }
+ return p.pagers[p.PageNumber()]
+}
+
+// First returns the pager for the first page.
+func (p *pager) First() *pager {+ if p.TotalPages() == 0 {+ return nil
+ }
+
+ return p.pagers[0]
+}
+
+// Last returns the pager for the last page.
+func (p *pager) Last() *pager {+ if p.TotalPages() == 0 {+ return nil
+ }
+
+ return p.pagers[len(p.pagers)-1]
+}
+
+// Pagers returns a list of pagers that can be used to build a pagination menu.
+func (p *paginator) Pagers() pagers {+ return p.pagers
+}
+
+// PageSize returns the size of each paginator page.
+func (p *paginator) PageSize() int {+ return p.size
+}
+
+// TotalPages returns the number of pages in the paginator.
+func (p *paginator) TotalPages() int {+ return len(p.paginatedPages)
+}
+
+// TotalNumberOfElements returns the number of elements on all pages in this paginator.
+func (p *paginator) TotalNumberOfElements() int {+ return p.total
+}
+
+func splitPages(pages Pages, size int) []Pages {+ var split []Pages
+ for low, j := 0, len(pages); low < j; low += size {+ high := int(math.Min(float64(low+size), float64(len(pages))))
+ split = append(split, pages[low:high])
+ }
+
+ return split
+}
+
+// Paginate gets this Node's paginator if it's already created.
+// If it's not, one will be created with all pages in Data["Pages"].
+func (n *Node) Paginator() (*pager, error) {+
+ if n.IsPage() {+ return nil, errors.New("Paginators isn't supported for content pages.")+ }
+
+ var initError error
+
+ n.paginatorInit.Do(func() {+ if n.paginator != nil {+ return
+ }
+
+ pagers, err := paginatePages(n.Data["Pages"], n.Url)
+
+ if err != nil {+ initError = err
+ }
+
+ if len(pagers) > 0 {+ // the rest of the nodes will be created later
+ n.paginator = pagers[0]
+ n.Site.addToPaginationPageCount(uint64(n.paginator.TotalPages()))
+ }
+
+ })
+
+ if initError != nil {+ return nil, initError
+ }
+
+ return n.paginator, nil
+}
+
+// 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 *Node) Paginate(seq interface{}) (*pager, error) {+
+ if n.IsPage() {+ return nil, errors.New("Paginators isn't supported for content pages.")+ }
+
+ var initError error
+
+ n.paginatorInit.Do(func() {+ if n.paginator != nil {+ return
+ }
+ pagers, err := paginatePages(seq, n.Url)
+
+ if err != nil {+ initError = err
+ }
+
+ if len(pagers) > 0 {+ // the rest of the nodes will be created later
+ n.paginator = pagers[0]
+ n.Site.addToPaginationPageCount(uint64(n.paginator.TotalPages()))
+ }
+
+ })
+
+ if initError != nil {+ return nil, initError
+ }
+
+ return n.paginator, nil
+}
+
+func paginatePages(seq interface{}, section string) (pagers, error) {+ paginateSize := viper.GetInt("paginate")+
+ if paginateSize <= 0 {+ return nil, errors.New("'paginate' configuration setting must be positive to paginate")+ }
+ var pages Pages
+ switch seq.(type) {+ case Pages:
+ pages = seq.(Pages)
+ case *Pages:
+ pages = *(seq.(*Pages))
+ case WeightedPages:
+ pages = (seq.(WeightedPages)).Pages()
+ case PageGroup:
+ pages = (seq.(PageGroup)).Pages
+ default:
+ return nil, errors.New(fmt.Sprintf("unsupported type in paginate, got %T", seq))+ }
+
+ urlFactory := newPaginationUrlFactory(section)
+ paginator := newPaginator(pages, paginateSize, urlFactory)
+ pagers := paginator.Pagers()
+
+ return pagers, nil
+}
+
+func newPaginator(pages Pages, size int, urlFactory paginationUrlFactory) *paginator {+
+ if size <= 0 {+ panic("Paginator size must be positive")+ }
+
+ split := splitPages(pages, size)
+
+ p := &paginator{total: len(pages), paginatedPages: split, size: size, paginationUrlFactory: urlFactory}+ pagers := make(pagers, len(split))
+
+ for i := range p.paginatedPages {+ pagers[i] = &pager{number: (i + 1), paginator: p}+ }
+
+ p.pagers = pagers
+
+ return p
+}
+
+func newPaginationUrlFactory(pathElements ...string) paginationUrlFactory {+ paginatePath := viper.GetString("paginatePath")+
+ return func(page int) string {+ var rel string
+ if page == 1 {+ rel = fmt.Sprintf("/%s/", path.Join(pathElements...))+ } else {+ rel = fmt.Sprintf("/%s/%s/%d/", path.Join(pathElements...), paginatePath, page)+ }
+
+ return helpers.UrlizeAndPrep(rel)
+ }
+}
--- /dev/null
+++ b/hugolib/pagination_test.go
@@ -1,0 +1,95 @@
+package hugolib
+
+import (
+ "fmt"
+ "github.com/spf13/hugo/source"
+ "github.com/spf13/viper"
+ "github.com/stretchr/testify/assert"
+ "path/filepath"
+ "testing"
+)
+
+func TestSplitPages(t *testing.T) {+
+ pages := createTestPages(21)
+ chunks := splitPages(pages, 5)
+ assert.Equal(t, 5, len(chunks))
+
+ for i := 0; i < 4; i++ {+ assert.Equal(t, 5, len(chunks[i]))
+ }
+
+ lastChunk := chunks[4]
+ assert.Equal(t, 1, len(lastChunk))
+
+}
+
+func TestPaginator(t *testing.T) {+
+ pages := createTestPages(21)
+ urlFactory := func(page int) string {+ return fmt.Sprintf("page/%d/", page)+ }
+
+ paginator := newPaginator(pages, 5, urlFactory)
+ paginatorPages := paginator.Pagers()
+
+ assert.Equal(t, 5, len(paginatorPages))
+ assert.Equal(t, 21, paginator.TotalNumberOfElements())
+ assert.Equal(t, 5, paginator.PageSize())
+ assert.Equal(t, 5, paginator.TotalPages())
+
+ first := paginatorPages[0]
+ assert.Equal(t, "page/1/", first.Url())
+ assert.Equal(t, first, first.First())
+ assert.Equal(t, true, first.HasNext())
+ assert.Equal(t, false, first.HasPrev())
+ assert.Equal(t, 5, first.NumberOfElements())
+ assert.Equal(t, 1, first.PageNumber())
+
+ third := paginatorPages[2]
+ assert.Equal(t, true, third.HasNext())
+ assert.Equal(t, true, third.HasPrev())
+
+ last := paginatorPages[4]
+ assert.Equal(t, "page/5/", last.Url())
+ assert.Equal(t, last, last.Last())
+ assert.Equal(t, false, last.HasNext())
+ assert.Equal(t, true, last.HasPrev())
+ assert.Equal(t, 1, last.NumberOfElements())
+ assert.Equal(t, 5, last.PageNumber())
+
+}
+
+func TestPaginationUrlFactory(t *testing.T) {+ viper.Set("PaginatePath", "zoo")+ 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))
+
+}
+
+func createTestPages(num int) Pages {+ pages := make(Pages, num)
+
+ for i := 0; i < num; i++ {+ pages[i] = &Page{+ Node: Node{+ UrlPath: UrlPath{+ Section: "z",
+ Url: fmt.Sprintf("http://base/x/y/p%d.html", num),+ },
+ Site: &SiteInfo{+ BaseUrl: "http://base/",
+ },
+ },
+ Source: Source{File: *source.NewFile(filepath.FromSlash(fmt.Sprintf("/x/y/p%d.md", num)))},+ }
+ }
+
+ return pages
+}
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -21,6 +21,7 @@
"io"
"net/url"
"os"
+ "path/filepath"
"strconv"
"strings"
"sync"
@@ -37,6 +38,7 @@
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/nitro"
"github.com/spf13/viper"
+ "sync/atomic"
)
var _ = transform.AbsURL
@@ -86,27 +88,28 @@
}
type SiteInfo struct {- BaseUrl template.URL
- Taxonomies TaxonomyList
- Authors AuthorList
- Social SiteSocial
- Indexes *TaxonomyList // legacy, should be identical to Taxonomies
- Sections Taxonomy
- Pages *Pages
- Files []*source.File
- Recent *Pages // legacy, should be identical to Pages
- Menus *Menus
- Hugo *HugoInfo
- Title string
- Author map[string]interface{}- LanguageCode string
- DisqusShortname string
- Copyright string
- LastChange time.Time
- Permalinks PermalinkOverrides
- Params map[string]interface{}- BuildDrafts bool
- canonifyUrls bool
+ BaseUrl template.URL
+ Taxonomies TaxonomyList
+ Authors AuthorList
+ Social SiteSocial
+ Indexes *TaxonomyList // legacy, should be identical to Taxonomies
+ Sections Taxonomy
+ Pages *Pages
+ Files []*source.File
+ Recent *Pages // legacy, should be identical to Pages
+ Menus *Menus
+ Hugo *HugoInfo
+ Title string
+ Author map[string]interface{}+ LanguageCode string
+ DisqusShortname string
+ Copyright string
+ LastChange time.Time
+ Permalinks PermalinkOverrides
+ Params map[string]interface{}+ BuildDrafts bool
+ canonifyUrls bool
+ paginationPageCount uint64
}
// SiteSocial is a place to put social details on a site level. These are the
@@ -205,6 +208,10 @@
return s.refLink(ref, page, true)
}
+func (s *SiteInfo) addToPaginationPageCount(cnt uint64) {+ atomic.AddUint64(&s.paginationPageCount, cnt)
+}
+
type runmode struct {Watching bool
}
@@ -614,7 +621,7 @@
if strings.HasPrefix(menuEntry.Url, "/") {// make it match the nodes
menuEntryUrl := menuEntry.Url
- menuEntryUrl = s.prepUrl(menuEntryUrl)
+ menuEntryUrl = helpers.UrlizeAndPrep(menuEntryUrl)
if !s.Info.canonifyUrls {menuEntryUrl = helpers.AddContextRoot(string(s.Info.BaseUrl), menuEntryUrl)
}
@@ -943,17 +950,63 @@
func taxonomyRenderer(s *Site, taxes <-chan taxRenderInfo, results chan<- error, wg *sync.WaitGroup) {defer wg.Done()
+
+ var n *Node
+
for t := range taxes {- n, base := s.newTaxonomyNode(t)
- layouts := []string{"taxonomy/" + t.singular + ".html", "indexes/" + t.singular + ".html", "_default/taxonomy.html", "_default/list.html"}- b, err := s.renderPage("taxononomy "+t.singular, n, s.appendThemeTemplates(layouts)...)+
+ var base string
+ layouts := s.appendThemeTemplates(
+ []string{"taxonomy/" + t.singular + ".html", "indexes/" + t.singular + ".html", "_default/taxonomy.html", "_default/list.html"})+
+ n, base = s.newTaxonomyNode(t)
+
+ b, err := s.renderPage("taxononomy "+t.singular, n, layouts...) if err != nil {results <- err
continue
- } else {- err := s.WriteDestPage(base+".html", b)
- if err != nil {- results <- err
+ }
+
+ err = s.WriteDestPage(base, b)
+ if err != nil {+ results <- err
+ continue
+ }
+
+ if n.paginator != nil {+
+ paginatePath := viper.GetString("paginatePath")+
+ // write alias for page 1
+ s.WriteDestAlias(fmt.Sprintf("%s/%s/%d/index.html", base, paginatePath, 1), s.permalink(base))+
+ pagers := n.paginator.Pagers()
+
+ for i, pager := range pagers {+ if i == 0 {+ // already created
+ continue
+ }
+
+ taxonomyPagerNode, _ := s.newTaxonomyNode(t)
+ taxonomyPagerNode.paginator = pager
+ if pager.TotalPages() > 0 {+ taxonomyPagerNode.Date = pager.Pages()[0].Date
+ }
+ pageNumber := i + 1
+ htmlBase := fmt.Sprintf("/%s/%s/%d", base, paginatePath, pageNumber)+ b, err := s.renderPage(fmt.Sprintf("taxononomy_%s_%d", t.singular, pageNumber), taxonomyPagerNode, layouts...)+ if err != nil {+ results <- err
+ continue
+ }
+
+ err = s.WriteDestPage(htmlBase, b)
+ if err != nil {+ results <- err
+ continue
+ }
+
}
}
@@ -1005,34 +1058,76 @@
return
}
+func (s *Site) newSectionListNode(section string, data WeightedPages) *Node {+ n := s.NewNode()
+ if viper.GetBool("PluralizeListTitles") {+ n.Title = strings.Title(inflect.Pluralize(section))
+ } else {+ n.Title = strings.Title(section)
+ }
+ s.setUrls(n, section)
+ n.Date = data[0].Page.Date
+ n.Data["Pages"] = data.Pages()
+
+ return n
+}
+
// Render a page for each section
func (s *Site) RenderSectionLists() error { for section, data := range s.Sections {- n := s.NewNode()
- if viper.GetBool("PluralizeListTitles") {- n.Title = strings.Title(inflect.Pluralize(section))
- } else {- n.Title = strings.Title(section)
- }
- s.setUrls(n, section)
- n.Date = data[0].Page.Date
- n.Data["Pages"] = data.Pages()
- layouts := []string{"section/" + section + ".html", "_default/section.html", "_default/list.html", "indexes/" + section + ".html", "_default/indexes.html"}- b, err := s.renderPage("section "+section, n, s.appendThemeTemplates(layouts)...)+ layouts := s.appendThemeTemplates(
+ []string{"section/" + section + ".html", "_default/section.html", "_default/list.html", "indexes/" + section + ".html", "_default/indexes.html"})+
+ n := s.newSectionListNode(section, data)
+
+ b, err := s.renderPage(fmt.Sprintf("section%s_%d", section, 1), n, s.appendThemeTemplates(layouts)...) if err != nil {return err
}
- if err := s.WriteDestPage(section, b); err != nil {+ if err := s.WriteDestPage(fmt.Sprintf("/%s", section), b); err != nil {return err
}
+ if n.paginator != nil {+
+ paginatePath := viper.GetString("paginatePath")+
+ // write alias for page 1
+ s.WriteDestAlias(filepath.FromSlash(fmt.Sprintf("/%s/%s/%d", section, paginatePath, 1)), s.permalink(section))+
+ pagers := n.paginator.Pagers()
+
+ for i, pager := range pagers {+ if i == 0 {+ // already created
+ continue
+ }
+
+ sectionPagerNode := s.newSectionListNode(section, data)
+ sectionPagerNode.paginator = pager
+ if pager.TotalPages() > 0 {+ sectionPagerNode.Date = pager.Pages()[0].Date
+ }
+ pageNumber := i + 1
+ htmlBase := fmt.Sprintf("/%s/%s/%d", section, paginatePath, pageNumber)+ b, err := s.renderPage(fmt.Sprintf("section_%s_%d", section, pageNumber), sectionPagerNode, layouts...)+ if err != nil {+ return err
+ }
+ if err := s.WriteDestPage(filepath.FromSlash(htmlBase), b); err != nil {+ return err
+ }
+
+ }
+ }
+
if !viper.GetBool("DisableRSS") && section != "" {// XML Feed
n.Url = s.permalinkStr(section + "/index.xml")
n.Permalink = s.permalink(section)
rssLayouts := []string{"section/" + section + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}- b, err = s.renderXML("section "+section+" rss", n, s.appendThemeTemplates(rssLayouts)...)+ b, err := s.renderXML("section "+section+" rss", n, s.appendThemeTemplates(rssLayouts)...) if err != nil {return err
}
@@ -1054,8 +1149,10 @@
func (s *Site) RenderHomePage() error {n := s.newHomeNode()
- layouts := []string{"index.html", "_default/list.html", "_default/single.html"}- b, err := s.renderPage("homepage", n, s.appendThemeTemplates(layouts)...)+ layouts := s.appendThemeTemplates([]string{"index.html", "_default/list.html", "_default/single.html"})+
+ b, err := s.renderPage("homepage", n, layouts...)+
if err != nil {return err
}
@@ -1063,6 +1160,39 @@
return err
}
+ if n.paginator != nil {+
+ paginatePath := viper.GetString("paginatePath")+
+ // write alias for page 1
+ s.WriteDestAlias(filepath.FromSlash(fmt.Sprintf("/%s/%d", paginatePath, 1)), s.permalink("/"))+
+ pagers := n.paginator.Pagers()
+
+ for i, pager := range pagers {+ if i == 0 {+ // already created
+ continue
+ }
+
+ homePagerNode := s.newHomeNode()
+ homePagerNode.paginator = pager
+ if pager.TotalPages() > 0 {+ homePagerNode.Date = pager.Pages()[0].Date
+ }
+ pageNumber := i + 1
+ htmlBase := fmt.Sprintf("/%s/%d", paginatePath, pageNumber)+ b, err := s.renderPage(fmt.Sprintf("homepage_%d", pageNumber), homePagerNode, layouts...)+ if err != nil {+ return err
+ }
+ if err := s.WriteDestPage(filepath.FromSlash(htmlBase), b); err != nil {+ return err
+ }
+
+ }
+ }
+
if !viper.GetBool("DisableRSS") {// XML Feed
n.Url = s.permalinkStr("index.xml")@@ -1163,7 +1293,9 @@
jww.FEEDBACK.Println(s.draftStats())
jww.FEEDBACK.Println(s.futureStats())
jww.FEEDBACK.Printf("%d pages created \n", len(s.Pages))-
+ if viper.GetInt("paginate") > 0 {+ jww.FEEDBACK.Printf("%d paginator pages created \n", s.Info.paginationPageCount)+ }
taxonomies := viper.GetStringMapString("Taxonomies") for _, pl := range taxonomies {@@ -1172,7 +1304,7 @@
}
func (s *Site) setUrls(n *Node, in string) {- n.Url = s.prepUrl(in)
+ n.Url = helpers.UrlizeAndPrep(in)
n.Permalink = s.permalink(n.Url)
n.RSSLink = s.permalink(in + ".xml")
}
@@ -1182,19 +1314,7 @@
}
func (s *Site) permalinkStr(plink string) string {- return helpers.MakePermalink(string(viper.GetString("BaseUrl")), s.prepUrl(plink)).String()-}
-
-func (s *Site) prepUrl(in string) string {- return s.PrettifyUrl(helpers.Urlize(in))
-}
-
-func (s *Site) PrettifyUrl(in string) string {- return helpers.UrlPrep(viper.GetBool("UglyUrls"), in)-}
-
-func (s *Site) PrettifyPath(in string) string {- return helpers.PathPrep(viper.GetBool("UglyUrls"), in)+ return helpers.MakePermalink(string(viper.GetString("BaseUrl")), helpers.UrlizeAndPrep(plink)).String()}
func (s *Site) NewNode() *Node {--- a/hugolib/site_url_test.go
+++ b/hugolib/site_url_test.go
@@ -56,6 +56,7 @@
hugofs.DestinationFS = new(afero.MemMapFs)
viper.Set("uglyurls", false)+ viper.Set("paginate", 10) s := &Site{ Source: &source.InMemorySource{ByteSource: urlFakeSource},}
--
⑨