summaryrefslogtreecommitdiffstats
path: root/hugolib/taxonomy.go
diff options
context:
space:
mode:
authorspf13 <steve.francia@gmail.com>2014-04-08 23:15:57 -0400
committerspf13 <steve.francia@gmail.com>2014-04-09 17:15:04 -0400
commit93bcddebb3030705dcb643dffb65890a270b5182 (patch)
tree46dac123f4ea8320d7dde2823b0d7c7df75688d0 /hugolib/taxonomy.go
parentaae6fa0b6b6319187992231baf773768585820d6 (diff)
Renamed Indexes to Taxonomies. Old template and config parameters still work.
Diffstat (limited to 'hugolib/taxonomy.go')
-rw-r--r--hugolib/taxonomy.go171
1 files changed, 171 insertions, 0 deletions
diff --git a/hugolib/taxonomy.go b/hugolib/taxonomy.go
new file mode 100644
index 000000000..5bb69eb90
--- /dev/null
+++ b/hugolib/taxonomy.go
@@ -0,0 +1,171 @@
+// Copyright © 2013 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 (
+ "sort"
+
+ "github.com/spf13/hugo/helpers"
+)
+
+/*
+ * An taxonomy list is a list of all taxonomies and their values
+ * EG. List['tags'] => TagTaxonomy (from above)
+ */
+type TaxonomyList map[string]Taxonomy
+
+/*
+ * An taxonomy is a map of keywords to a list of pages.
+ * For example
+ * TagTaxonomy['technology'] = WeightedPages
+ * TagTaxonomy['go'] = WeightedPages2
+ */
+type Taxonomy map[string]WeightedPages
+
+/*
+ * A list of Pages with their corresponding (and relative) weight
+ * [{Weight: 30, Page: *1}, {Weight: 40, Page: *2}]
+ */
+type WeightedPages []WeightedPage
+type WeightedPage struct {
+ Weight int
+ Page *Page
+}
+
+/*
+ * This is another representation of an Taxonomy using an array rather than a map.
+ * Important because you can't order a map.
+ */
+type OrderedTaxonomy []OrderedTaxonomyEntry
+
+/*
+ * Similar to an element of an Taxonomy, but with the key embedded (as name)
+ * Eg: {Name: Technology, WeightedPages: Taxonomyedpages}
+ */
+type OrderedTaxonomyEntry struct {
+ Name string
+ WeightedPages WeightedPages
+}
+
+// KeyPrep... Taxonomies should be case insensitive. Can make it easily conditional later.
+func kp(in string) string {
+ return helpers.MakePath(in)
+}
+
+func (i Taxonomy) Get(key string) WeightedPages { return i[kp(key)] }
+func (i Taxonomy) Count(key string) int { return len(i[kp(key)]) }
+func (i Taxonomy) Add(key string, w WeightedPage) {
+ key = kp(key)
+ i[key] = append(i[key], w)
+}
+
+// Returns an ordered taxonomy with a non defined order
+func (i Taxonomy) TaxonomyArray() OrderedTaxonomy {
+ ies := make([]OrderedTaxonomyEntry, len(i))
+ count := 0
+ for k, v := range i {
+ ies[count] = OrderedTaxonomyEntry{Name: k, WeightedPages: v}
+ count++
+ }
+ return ies
+}
+
+// Returns an ordered taxonomy sorted by key name
+func (i Taxonomy) Alphabetical() OrderedTaxonomy {
+ name := func(i1, i2 *OrderedTaxonomyEntry) bool {
+ return i1.Name < i2.Name
+ }
+
+ ia := i.TaxonomyArray()
+ OIby(name).Sort(ia)
+ return ia
+}
+
+// Returns an ordered taxonomy sorted by # of pages per key
+func (i Taxonomy) ByCount() OrderedTaxonomy {
+ count := func(i1, i2 *OrderedTaxonomyEntry) bool {
+ return len(i1.WeightedPages) > len(i2.WeightedPages)
+ }
+
+ ia := i.TaxonomyArray()
+ OIby(count).Sort(ia)
+ return ia
+}
+
+// Helper to move the page access up a level
+func (ie OrderedTaxonomyEntry) Pages() []*Page {
+ return ie.WeightedPages.Pages()
+}
+
+func (ie OrderedTaxonomyEntry) Count() int {
+ return len(ie.WeightedPages)
+}
+
+/*
+ * Implementation of a custom sorter for OrderedTaxonomies
+ */
+
+// A type to implement the sort interface for TaxonomyEntries.
+type orderedTaxonomySorter struct {
+ taxonomy OrderedTaxonomy
+ by OIby
+}
+
+// Closure used in the Sort.Less method.
+type OIby func(i1, i2 *OrderedTaxonomyEntry) bool
+
+func (by OIby) Sort(taxonomy OrderedTaxonomy) {
+ ps := &orderedTaxonomySorter{
+ taxonomy: taxonomy,
+ by: by, // The Sort method's receiver is the function (closure) that defines the sort order.
+ }
+ sort.Sort(ps)
+}
+
+// Len is part of sort.Interface.
+func (s *orderedTaxonomySorter) Len() int {
+ return len(s.taxonomy)
+}
+
+// Swap is part of sort.Interface.
+func (s *orderedTaxonomySorter) Swap(i, j int) {
+ s.taxonomy[i], s.taxonomy[j] = s.taxonomy[j], s.taxonomy[i]
+}
+
+// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
+func (s *orderedTaxonomySorter) Less(i, j int) bool {
+ return s.by(&s.taxonomy[i], &s.taxonomy[j])
+}
+
+func (wp WeightedPages) Pages() Pages {
+ pages := make(Pages, len(wp))
+ for i := range wp {
+ pages[i] = wp[i].Page
+ }
+ return pages
+}
+
+func (p WeightedPages) Len() int { return len(p) }
+func (p WeightedPages) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+func (p WeightedPages) Sort() { sort.Sort(p) }
+func (p WeightedPages) Count() int { return len(p) }
+func (p WeightedPages) Less(i, j int) bool {
+ if p[i].Weight == p[j].Weight {
+ return p[i].Page.Date.Unix() > p[j].Page.Date.Unix()
+ } else {
+ return p[i].Weight < p[j].Weight
+ }
+}
+
+// TODO mimic PagesSorter for WeightedPages