taxonomy.go - hugo - [fork] hugo port for 9front
(HTM) git clone https://git.drkhsh.at/hugo.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
taxonomy.go (4887B)
---
1 // Copyright 2024 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 "strings"
20
21 "github.com/gohugoio/hugo/compare"
22 "github.com/gohugoio/hugo/langs"
23 )
24
25 // The TaxonomyList is a list of all taxonomies and their values
26 // e.g. List['tags'] => TagTaxonomy (from above)
27 type TaxonomyList map[string]Taxonomy
28
29 func (tl TaxonomyList) String() string {
30 return fmt.Sprintf("TaxonomyList(%d)", len(tl))
31 }
32
33 // A Taxonomy is a map of keywords to a list of pages.
34 // For example
35 //
36 // TagTaxonomy['technology'] = WeightedPages
37 // TagTaxonomy['go'] = WeightedPages
38 type Taxonomy map[string]WeightedPages
39
40 // OrderedTaxonomy is another representation of an Taxonomy using an array rather than a map.
41 // Important because you can't order a map.
42 type OrderedTaxonomy []OrderedTaxonomyEntry
43
44 // getOneOPage returns one page in the taxonomy,
45 // nil if there is none.
46 func (t OrderedTaxonomy) getOneOPage() Page {
47 if len(t) == 0 {
48 return nil
49 }
50 return t[0].Pages()[0]
51 }
52
53 // OrderedTaxonomyEntry is similar to an element of a Taxonomy, but with the key embedded (as name)
54 // e.g: {Name: Technology, WeightedPages: TaxonomyPages}
55 type OrderedTaxonomyEntry struct {
56 Name string
57 WeightedPages
58 }
59
60 // Get the weighted pages for the given key.
61 func (i Taxonomy) Get(key string) WeightedPages {
62 return i[strings.ToLower(key)]
63 }
64
65 // Count the weighted pages for the given key.
66 func (i Taxonomy) Count(key string) int { return len(i[strings.ToLower(key)]) }
67
68 // TaxonomyArray returns an ordered taxonomy with a non defined order.
69 func (i Taxonomy) TaxonomyArray() OrderedTaxonomy {
70 ies := make([]OrderedTaxonomyEntry, len(i))
71 count := 0
72 for k, v := range i {
73 ies[count] = OrderedTaxonomyEntry{Name: k, WeightedPages: v}
74 count++
75 }
76 return ies
77 }
78
79 // Alphabetical returns an ordered taxonomy sorted by key name.
80 func (i Taxonomy) Alphabetical() OrderedTaxonomy {
81 ia := i.TaxonomyArray()
82 p := ia.getOneOPage()
83 if p == nil {
84 return ia
85 }
86 currentSite := p.Site().Current()
87 coll := langs.GetCollator1(currentSite.Language())
88 coll.Lock()
89 defer coll.Unlock()
90 name := func(i1, i2 *OrderedTaxonomyEntry) bool {
91 return coll.CompareStrings(i1.Name, i2.Name) < 0
92 }
93 oiBy(name).Sort(ia)
94 return ia
95 }
96
97 // ByCount returns an ordered taxonomy sorted by # of pages per key.
98 // If taxonomies have the same # of pages, sort them alphabetical
99 func (i Taxonomy) ByCount() OrderedTaxonomy {
100 count := func(i1, i2 *OrderedTaxonomyEntry) bool {
101 li1 := len(i1.WeightedPages)
102 li2 := len(i2.WeightedPages)
103
104 if li1 == li2 {
105 return compare.LessStrings(i1.Name, i2.Name)
106 }
107 return li1 > li2
108 }
109
110 ia := i.TaxonomyArray()
111 oiBy(count).Sort(ia)
112 return ia
113 }
114
115 // Page returns the taxonomy page or nil if the taxonomy has no terms.
116 func (i Taxonomy) Page() Page {
117 for _, v := range i {
118 return v.Page().Parent()
119 }
120 return nil
121 }
122
123 // Pages returns the Pages for this taxonomy.
124 func (ie OrderedTaxonomyEntry) Pages() Pages {
125 return ie.WeightedPages.Pages()
126 }
127
128 // Count returns the count the pages in this taxonomy.
129 func (ie OrderedTaxonomyEntry) Count() int {
130 return len(ie.WeightedPages)
131 }
132
133 // Term returns the name given to this taxonomy.
134 func (ie OrderedTaxonomyEntry) Term() string {
135 return ie.Name
136 }
137
138 // Reverse reverses the order of the entries in this taxonomy.
139 func (t OrderedTaxonomy) Reverse() OrderedTaxonomy {
140 for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {
141 t[i], t[j] = t[j], t[i]
142 }
143
144 return t
145 }
146
147 // A type to implement the sort interface for TaxonomyEntries.
148 type orderedTaxonomySorter struct {
149 taxonomy OrderedTaxonomy
150 by oiBy
151 }
152
153 // Closure used in the Sort.Less method.
154 type oiBy func(i1, i2 *OrderedTaxonomyEntry) bool
155
156 func (by oiBy) Sort(taxonomy OrderedTaxonomy) {
157 ps := &orderedTaxonomySorter{
158 taxonomy: taxonomy,
159 by: by, // The Sort method's receiver is the function (closure) that defines the sort order.
160 }
161 sort.Stable(ps)
162 }
163
164 // Len is part of sort.Interface.
165 func (s *orderedTaxonomySorter) Len() int {
166 return len(s.taxonomy)
167 }
168
169 // Swap is part of sort.Interface.
170 func (s *orderedTaxonomySorter) Swap(i, j int) {
171 s.taxonomy[i], s.taxonomy[j] = s.taxonomy[j], s.taxonomy[i]
172 }
173
174 // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
175 func (s *orderedTaxonomySorter) Less(i, j int) bool {
176 return s.by(&s.taxonomy[i], &s.taxonomy[j])
177 }