mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
hugolib: Fix panic for unused taxonomy content files
In Hugo 0.55 we connected the taxonomy nodes with their owning Page. This failed if you had, say, a content file for a author that did not author anything in the site: ``` content/authors/silent-persin/_index.md ``` Fixes #5847
This commit is contained in:
parent
701486728e
commit
b799b12f4a
5 changed files with 52 additions and 17 deletions
|
@ -14,7 +14,9 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -650,7 +652,19 @@ func (h *HugoSites) createMissingPages() error {
|
||||||
|
|
||||||
// Make them navigable from WeightedPage etc.
|
// Make them navigable from WeightedPage etc.
|
||||||
for _, p := range taxonomyPages {
|
for _, p := range taxonomyPages {
|
||||||
p.getTaxonomyNodeInfo().TransferValues(p)
|
ni := p.getTaxonomyNodeInfo()
|
||||||
|
if ni == nil {
|
||||||
|
// This can be nil for taxonomies, e.g. an author,
|
||||||
|
// with a content file, but no actual usage.
|
||||||
|
// Create one.
|
||||||
|
sections := p.SectionsEntries()
|
||||||
|
if len(sections) < 2 {
|
||||||
|
// Invalid state
|
||||||
|
panic(fmt.Sprintf("invalid taxonomy state for %q with sections %v", p.pathOrTitle(), sections))
|
||||||
|
}
|
||||||
|
ni = p.s.taxonomyNodes.GetOrAdd(sections[0], path.Join(sections[1:]...))
|
||||||
|
}
|
||||||
|
ni.TransferValues(p)
|
||||||
}
|
}
|
||||||
for _, p := range taxonomyTermsPages {
|
for _, p := range taxonomyTermsPages {
|
||||||
p.getTaxonomyNodeInfo().TransferValues(p)
|
p.getTaxonomyNodeInfo().TransferValues(p)
|
||||||
|
|
|
@ -746,8 +746,10 @@ func (p *pageState) getTaxonomyNodeInfo() *taxonomyNodeInfo {
|
||||||
info := p.s.taxonomyNodes.Get(p.SectionsEntries()...)
|
info := p.s.taxonomyNodes.Get(p.SectionsEntries()...)
|
||||||
|
|
||||||
if info == nil {
|
if info == nil {
|
||||||
// This should never happpen
|
// There can be unused content pages for taxonomies (e.g. author that
|
||||||
panic(fmt.Sprintf("invalid taxonomy state for %q with sections %v", p.pathOrTitle(), p.SectionsEntries()))
|
// has not written anything, yet), and these will not have a taxonomy
|
||||||
|
// node created in the assemble taxonomies step.
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
|
@ -94,7 +94,7 @@ type Site struct {
|
||||||
|
|
||||||
Taxonomies TaxonomyList
|
Taxonomies TaxonomyList
|
||||||
|
|
||||||
taxonomyNodes taxonomyNodeInfos
|
taxonomyNodes *taxonomyNodeInfos
|
||||||
|
|
||||||
Sections Taxonomy
|
Sections Taxonomy
|
||||||
Info SiteInfo
|
Info SiteInfo
|
||||||
|
@ -1566,24 +1566,23 @@ func (s *Site) assembleTaxonomies() error {
|
||||||
s.Taxonomies[plural] = make(Taxonomy)
|
s.Taxonomies[plural] = make(Taxonomy)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.taxonomyNodes = make(taxonomyNodeInfos)
|
s.taxonomyNodes = &taxonomyNodeInfos{
|
||||||
|
m: make(map[string]*taxonomyNodeInfo),
|
||||||
|
getKey: s.getTaxonomyKey,
|
||||||
|
}
|
||||||
|
|
||||||
s.Log.INFO.Printf("found taxonomies: %#v\n", taxonomies)
|
s.Log.INFO.Printf("found taxonomies: %#v\n", taxonomies)
|
||||||
|
|
||||||
for singular, plural := range taxonomies {
|
for singular, plural := range taxonomies {
|
||||||
parent := s.taxonomyNodes.GetOrCreate(plural, "", "")
|
parent := s.taxonomyNodes.GetOrCreate(plural, "")
|
||||||
parent.singular = singular
|
parent.singular = singular
|
||||||
|
|
||||||
addTaxonomy := func(plural, term string, weight int, p page.Page) {
|
addTaxonomy := func(plural, term string, weight int, p page.Page) {
|
||||||
key := s.getTaxonomyKey(term)
|
key := s.getTaxonomyKey(term)
|
||||||
|
|
||||||
n := s.taxonomyNodes.GetOrCreate(plural, key, term)
|
n := s.taxonomyNodes.GetOrCreate(plural, term)
|
||||||
n.parent = parent
|
n.parent = parent
|
||||||
|
|
||||||
// There may be different spellings before normalization, so the
|
|
||||||
// last one will win, e.g. "hugo" vs "Hugo".
|
|
||||||
n.term = term
|
|
||||||
|
|
||||||
w := page.NewWeightedPage(weight, p, n.owner)
|
w := page.NewWeightedPage(weight, p, n.owner)
|
||||||
|
|
||||||
s.Taxonomies[plural].add(key, w)
|
s.Taxonomies[plural].add(key, w)
|
||||||
|
|
|
@ -193,16 +193,33 @@ func (t *taxonomyNodeInfo) TransferValues(p *pageState) {
|
||||||
|
|
||||||
// Maps either plural or plural/term to a taxonomy node.
|
// Maps either plural or plural/term to a taxonomy node.
|
||||||
// TODO(bep) consolidate somehow with s.Taxonomies
|
// TODO(bep) consolidate somehow with s.Taxonomies
|
||||||
type taxonomyNodeInfos map[string]*taxonomyNodeInfo
|
type taxonomyNodeInfos struct {
|
||||||
|
m map[string]*taxonomyNodeInfo
|
||||||
|
getKey func(string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
// map[string]*taxonomyNodeInfo
|
||||||
func (t taxonomyNodeInfos) key(parts ...string) string {
|
func (t taxonomyNodeInfos) key(parts ...string) string {
|
||||||
return path.Join(parts...)
|
return path.Join(parts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNodeInfo {
|
// GetOrAdd will get or create and add a new taxonomy node to the parent identified with plural.
|
||||||
|
// It will panic if the parent does not exist.
|
||||||
|
func (t taxonomyNodeInfos) GetOrAdd(plural, term string) *taxonomyNodeInfo {
|
||||||
|
parent := t.GetOrCreate(plural, "")
|
||||||
|
if parent == nil {
|
||||||
|
panic(fmt.Sprintf("no parent found with plural %q", plural))
|
||||||
|
}
|
||||||
|
child := t.GetOrCreate(plural, term)
|
||||||
|
child.parent = parent
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t taxonomyNodeInfos) GetOrCreate(plural, term string) *taxonomyNodeInfo {
|
||||||
|
termKey := t.getKey(term)
|
||||||
key := t.key(plural, termKey)
|
key := t.key(plural, termKey)
|
||||||
|
|
||||||
n, found := t[key]
|
n, found := t.m[key]
|
||||||
if found {
|
if found {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
@ -214,7 +231,7 @@ func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNo
|
||||||
owner: &page.PageWrapper{}, // Page will be assigned later.
|
owner: &page.PageWrapper{}, // Page will be assigned later.
|
||||||
}
|
}
|
||||||
|
|
||||||
t[key] = n
|
t.m[key] = n
|
||||||
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
@ -222,7 +239,7 @@ func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNo
|
||||||
func (t taxonomyNodeInfos) Get(sections ...string) *taxonomyNodeInfo {
|
func (t taxonomyNodeInfos) Get(sections ...string) *taxonomyNodeInfo {
|
||||||
key := t.key(sections...)
|
key := t.key(sections...)
|
||||||
|
|
||||||
n, found := t[key]
|
n, found := t.m[key]
|
||||||
if found {
|
if found {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,9 @@ permalinkeds:
|
||||||
writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10)
|
writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10)
|
||||||
writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/Tag1/_index.md", 10)
|
writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/Tag1/_index.md", 10)
|
||||||
|
|
||||||
|
// https://github.com/gohugoio/hugo/issues/5847
|
||||||
|
writeNewContentFile(t, fs.Source, "Unused Tag List", "2018-01-01", "content/tags/not-used/_index.md", 10)
|
||||||
|
|
||||||
err := h.Build(BuildCfg{})
|
err := h.Build(BuildCfg{})
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -159,7 +162,7 @@ permalinkeds:
|
||||||
// Make sure that each page.KindTaxonomyTerm page has an appropriate number
|
// Make sure that each page.KindTaxonomyTerm page has an appropriate number
|
||||||
// of page.KindTaxonomy pages in its Pages slice.
|
// of page.KindTaxonomy pages in its Pages slice.
|
||||||
taxonomyTermPageCounts := map[string]int{
|
taxonomyTermPageCounts := map[string]int{
|
||||||
"tags": 2,
|
"tags": 3,
|
||||||
"categories": 2,
|
"categories": 2,
|
||||||
"others": 2,
|
"others": 2,
|
||||||
"empties": 0,
|
"empties": 0,
|
||||||
|
|
Loading…
Reference in a new issue