hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

weighted.go (3626B)

    1 // Copyright 2019 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 package page
   15 
   16 import (
   17 	"fmt"
   18 	"sort"
   19 
   20 	"github.com/gohugoio/hugo/common/collections"
   21 )
   22 
   23 var _ collections.Slicer = WeightedPage{}
   24 
   25 // WeightedPages is a list of Pages with their corresponding (and relative) weight
   26 // [{Weight: 30, Page: *1}, {Weight: 40, Page: *2}]
   27 type WeightedPages []WeightedPage
   28 
   29 // Page will return the Page (of Kind taxonomyList) that represents this set
   30 // of pages. This method will panic if p is empty, as that should never happen.
   31 func (p WeightedPages) Page() Page {
   32 	if len(p) == 0 {
   33 		panic("WeightedPages is empty")
   34 	}
   35 
   36 	first := p[0]
   37 
   38 	// TODO(bep) fix tests
   39 	if first.owner == nil {
   40 		return nil
   41 	}
   42 
   43 	return first.owner
   44 }
   45 
   46 // A WeightedPage is a Page with a weight.
   47 type WeightedPage struct {
   48 	Weight int
   49 	Page
   50 
   51 	// Reference to the owning Page. This avoids having to do
   52 	// manual .Site.GetPage lookups. It is implemented in this roundabout way
   53 	// because we cannot add additional state to the WeightedPages slice
   54 	// without breaking lots of templates in the wild.
   55 	owner Page
   56 }
   57 
   58 func NewWeightedPage(weight int, p Page, owner Page) WeightedPage {
   59 	return WeightedPage{Weight: weight, Page: p, owner: owner}
   60 }
   61 
   62 func (w WeightedPage) String() string {
   63 	return fmt.Sprintf("WeightedPage(%d,%q)", w.Weight, w.Page.Title())
   64 }
   65 
   66 // Slice is for internal use.
   67 // for the template functions. See collections.Slice.
   68 func (p WeightedPage) Slice(in any) (any, error) {
   69 	switch items := in.(type) {
   70 	case WeightedPages:
   71 		return items, nil
   72 	case []any:
   73 		weighted := make(WeightedPages, len(items))
   74 		for i, v := range items {
   75 			g, ok := v.(WeightedPage)
   76 			if !ok {
   77 				return nil, fmt.Errorf("type %T is not a WeightedPage", v)
   78 			}
   79 			weighted[i] = g
   80 		}
   81 		return weighted, nil
   82 	default:
   83 		return nil, fmt.Errorf("invalid slice type %T", items)
   84 	}
   85 }
   86 
   87 // Pages returns the Pages in this weighted page set.
   88 func (wp WeightedPages) Pages() Pages {
   89 	pages := make(Pages, len(wp))
   90 	for i := range wp {
   91 		pages[i] = wp[i].Page
   92 	}
   93 	return pages
   94 }
   95 
   96 // Next returns the next Page relative to the given Page in
   97 // this weighted page set.
   98 func (wp WeightedPages) Next(cur Page) Page {
   99 	for x, c := range wp {
  100 		if c.Page.Eq(cur) {
  101 			if x == 0 {
  102 				return nil
  103 			}
  104 			return wp[x-1].Page
  105 		}
  106 	}
  107 	return nil
  108 }
  109 
  110 // Prev returns the previous Page relative to the given Page in
  111 // this weighted page set.
  112 func (wp WeightedPages) Prev(cur Page) Page {
  113 	for x, c := range wp {
  114 		if c.Page.Eq(cur) {
  115 			if x < len(wp)-1 {
  116 				return wp[x+1].Page
  117 			}
  118 			return nil
  119 		}
  120 	}
  121 	return nil
  122 }
  123 
  124 func (wp WeightedPages) Len() int      { return len(wp) }
  125 func (wp WeightedPages) Swap(i, j int) { wp[i], wp[j] = wp[j], wp[i] }
  126 
  127 // Sort stable sorts this weighted page set.
  128 func (wp WeightedPages) Sort() { sort.Stable(wp) }
  129 
  130 // Count returns the number of pages in this weighted page set.
  131 func (wp WeightedPages) Count() int { return len(wp) }
  132 
  133 func (wp WeightedPages) Less(i, j int) bool {
  134 	if wp[i].Weight == wp[j].Weight {
  135 		return DefaultPageSort(wp[i].Page, wp[j].Page)
  136 	}
  137 	return wp[i].Weight < wp[j].Weight
  138 }