diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-01-02 12:33:26 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-03-23 18:51:22 +0100 |
commit | 597e418cb02883418f2cebb41400e8e61413f651 (patch) | |
tree | 177ad9c540b2583b6dab138c9f0490d28989c7f7 /hugolib/taxonomy.go | |
parent | 44f5c1c14cb1f42cc5f01739c289e9cfc83602af (diff) |
Make Page an interface
The main motivation of this commit is to add a `page.Page` interface to replace the very file-oriented `hugolib.Page` struct.
This is all a preparation step for issue #5074, "pages from other data sources".
But this also fixes a set of annoying limitations, especially related to custom output formats, and shortcodes.
Most notable changes:
* The inner content of shortcodes using the `{{%` as the outer-most delimiter will now be sent to the content renderer, e.g. Blackfriday.
This means that any markdown will partake in the global ToC and footnote context etc.
* The Custom Output formats are now "fully virtualized". This removes many of the current limitations.
* The taxonomy list type now has a reference to the `Page` object.
This improves the taxonomy template `.Title` situation and make common template constructs much simpler.
See #5074
Fixes #5763
Fixes #5758
Fixes #5090
Fixes #5204
Fixes #4695
Fixes #5607
Fixes #5707
Fixes #5719
Fixes #3113
Fixes #5706
Fixes #5767
Fixes #5723
Fixes #5769
Fixes #5770
Fixes #5771
Fixes #5759
Fixes #5776
Fixes #5777
Fixes #5778
Diffstat (limited to 'hugolib/taxonomy.go')
-rw-r--r-- | hugolib/taxonomy.go | 151 |
1 files changed, 81 insertions, 70 deletions
diff --git a/hugolib/taxonomy.go b/hugolib/taxonomy.go index c8447d1ba..9d9e4f9ec 100644 --- a/hugolib/taxonomy.go +++ b/hugolib/taxonomy.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Hugo Authors. All rights reserved. +// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,11 @@ package hugolib import ( "fmt" + "path" "sort" + + "github.com/gohugoio/hugo/resources/page" + "github.com/gohugoio/hugo/resources/resource" ) // The TaxonomyList is a list of all taxonomies and their values @@ -28,44 +32,30 @@ func (tl TaxonomyList) String() string { // A Taxonomy is a map of keywords to a list of pages. // For example -// TagTaxonomy['technology'] = WeightedPages -// TagTaxonomy['go'] = WeightedPages2 -type Taxonomy map[string]WeightedPages - -// WeightedPages is a list of Pages with their corresponding (and relative) weight -// [{Weight: 30, Page: *1}, {Weight: 40, Page: *2}] -type WeightedPages []WeightedPage - -// A WeightedPage is a Page with a weight. -type WeightedPage struct { - Weight int - *Page -} - -func (w WeightedPage) String() string { - return fmt.Sprintf("WeightedPage(%d,%q)", w.Weight, w.Page.title) -} +// TagTaxonomy['technology'] = page.WeightedPages +// TagTaxonomy['go'] = page.WeightedPages +type Taxonomy map[string]page.WeightedPages // OrderedTaxonomy is another representation of an Taxonomy using an array rather than a map. // Important because you can't order a map. type OrderedTaxonomy []OrderedTaxonomyEntry // OrderedTaxonomyEntry is similar to an element of a Taxonomy, but with the key embedded (as name) -// e.g: {Name: Technology, WeightedPages: Taxonomyedpages} +// e.g: {Name: Technology, page.WeightedPages: TaxonomyPages} type OrderedTaxonomyEntry struct { - Name string - WeightedPages WeightedPages + Name string + page.WeightedPages } // Get the weighted pages for the given key. -func (i Taxonomy) Get(key string) WeightedPages { +func (i Taxonomy) Get(key string) page.WeightedPages { return i[key] } // Count the weighted pages for the given key. func (i Taxonomy) Count(key string) int { return len(i[key]) } -func (i Taxonomy) add(key string, w WeightedPage) { +func (i Taxonomy) add(key string, w page.WeightedPage) { i[key] = append(i[key], w) } @@ -110,7 +100,7 @@ func (i Taxonomy) ByCount() OrderedTaxonomy { } // Pages returns the Pages for this taxonomy. -func (ie OrderedTaxonomyEntry) Pages() Pages { +func (ie OrderedTaxonomyEntry) Pages() page.Pages { return ie.WeightedPages.Pages() } @@ -165,60 +155,81 @@ func (s *orderedTaxonomySorter) Less(i, j int) bool { return s.by(&s.taxonomy[i], &s.taxonomy[j]) } -// Pages returns the Pages in this weighted page set. -func (wp WeightedPages) Pages() Pages { - pages := make(Pages, len(wp)) - for i := range wp { - pages[i] = wp[i].Page - } - return pages -} - -// Prev returns the previous Page relative to the given Page in -// this weighted page set. -func (wp WeightedPages) Prev(cur *Page) *Page { - for x, c := range wp { - if c.Page.UniqueID() == cur.UniqueID() { - if x == 0 { - return wp[len(wp)-1].Page - } - return wp[x-1].Page - } - } - return nil +// taxonomyNodeInfo stores additional metadata about a taxonomy. +type taxonomyNodeInfo struct { + plural string + + // Maps "tags" to "tag". + singular string + + // The term key as used in the taxonomy map, e.g "tag1". + // The value is normalized for paths, but may or not be lowercased + // depending on the disablePathToLower setting. + termKey string + + // The original, unedited term name. Useful for titles etc. + term string + + dates resource.Dates + + parent *taxonomyNodeInfo + + // Either of Kind taxonomyTerm (parent) or taxonomy + owner page.Page } -// Next returns the next Page relative to the given Page in -// this weighted page set. -func (wp WeightedPages) Next(cur *Page) *Page { - for x, c := range wp { - if c.Page.UniqueID() == cur.UniqueID() { - if x < len(wp)-1 { - return wp[x+1].Page - } - return wp[0].Page - } +func (t *taxonomyNodeInfo) UpdateFromPage(p page.Page) { + + // Select the latest dates + t.dates.UpdateDateAndLastmodIfAfter(p) +} + +func (t *taxonomyNodeInfo) TransferValues(p *pageState) { + t.owner = p + if p.Lastmod().IsZero() && p.Date().IsZero() { + p.m.Dates.UpdateDateAndLastmodIfAfter(t.dates) } - return nil } -func (wp WeightedPages) Len() int { return len(wp) } -func (wp WeightedPages) Swap(i, j int) { wp[i], wp[j] = wp[j], wp[i] } +// callback sent to the child nodes. +func (t *taxonomyNodeInfo) getOwner() page.Page { + return t.owner +} -// Sort stable sorts this weighted page set. -func (wp WeightedPages) Sort() { sort.Stable(wp) } +// Maps either plural or plural/term to a taxonomy node. +// TODO(bep) consolidate somehow with s.Taxonomies +type taxonomyNodeInfos map[string]*taxonomyNodeInfo -// Count returns the number of pages in this weighted page set. -func (wp WeightedPages) Count() int { return len(wp) } +func (t taxonomyNodeInfos) key(parts ...string) string { + return path.Join(parts...) +} -func (wp WeightedPages) Less(i, j int) bool { - if wp[i].Weight == wp[j].Weight { - if wp[i].Page.Date.Equal(wp[j].Page.Date) { - return wp[i].Page.title < wp[j].Page.title - } - return wp[i].Page.Date.After(wp[i].Page.Date) +func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNodeInfo { + key := t.key(plural, termKey) + + n, found := t[key] + if found { + return n } - return wp[i].Weight < wp[j].Weight + + n = &taxonomyNodeInfo{ + plural: plural, + termKey: termKey, + term: term, + } + + t[key] = n + + return n } -// TODO mimic PagesSorter for WeightedPages +func (t taxonomyNodeInfos) Get(sections ...string) *taxonomyNodeInfo { + key := t.key(sections...) + + n, found := t[key] + if found { + return n + } + + return nil +} |