Create a struct with all of Hugo's config options

Primary motivation is documentation, but it will also hopefully simplify the code.

Also,

* Lower case the default output format names; this is in line with the custom ones (map keys) and how
it's treated all the places. This avoids doing `stringds.EqualFold` everywhere.

Closes #10896
Closes #10620
This commit is contained in:
Bjørn Erik Pedersen
2023-01-04 18:24:36 +01:00
parent 6aededf6b4
commit 241b21b0fd
337 changed files with 13377 additions and 14898 deletions

View File

@@ -19,6 +19,7 @@ import (
"strings"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/hugofs/glob"
"github.com/mitchellh/mapstructure"
)
@@ -80,43 +81,90 @@ func (m PageMatcher) Matches(p Page) bool {
return true
}
// DecodeCascade decodes in which could be either a map or a slice of maps.
func DecodeCascade(in any) (map[PageMatcher]maps.Params, error) {
m, err := maps.ToSliceStringMap(in)
if err != nil {
return map[PageMatcher]maps.Params{
{}: maps.ToStringMap(in),
}, nil
}
func DecodeCascadeConfig(in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, map[PageMatcher]maps.Params], error) {
buildConfig := func(in any) (map[PageMatcher]maps.Params, any, error) {
cascade := make(map[PageMatcher]maps.Params)
if in == nil {
return cascade, []map[string]any{}, nil
}
ms, err := maps.ToSliceStringMap(in)
if err != nil {
return nil, nil, err
}
cascade := make(map[PageMatcher]maps.Params)
var cfgs []PageMatcherParamsConfig
for _, vv := range m {
var m PageMatcher
if mv, found := vv["_target"]; found {
err := DecodePageMatcher(mv, &m)
for _, m := range ms {
m = maps.CleanConfigStringMap(m)
c, err := mapToPageMatcherParamsConfig(m)
if err != nil {
return nil, err
return nil, nil, err
}
cfgs = append(cfgs, c)
}
c, found := cascade[m]
if found {
// Merge
for k, v := range vv {
if _, found := c[k]; !found {
c[k] = v
for _, cfg := range cfgs {
m := cfg.Target
c, found := cascade[m]
if found {
// Merge
for k, v := range cfg.Params {
if _, found := c[k]; !found {
c[k] = v
}
}
} else {
cascade[m] = cfg.Params
}
} else {
cascade[m] = vv
}
return cascade, cfgs, nil
}
return cascade, nil
return config.DecodeNamespace[[]PageMatcherParamsConfig](in, buildConfig)
}
// DecodePageMatcher decodes m into v.
func DecodePageMatcher(m any, v *PageMatcher) error {
// DecodeCascade decodes in which could be either a map or a slice of maps.
func DecodeCascade(in any) (map[PageMatcher]maps.Params, error) {
conf, err := DecodeCascadeConfig(in)
if err != nil {
return nil, err
}
return conf.Config, nil
}
func mapToPageMatcherParamsConfig(m map[string]any) (PageMatcherParamsConfig, error) {
var pcfg PageMatcherParamsConfig
for k, v := range m {
switch strings.ToLower(k) {
case "params":
// We simplified the structure of the cascade config in Hugo 0.111.0.
// There is a small chance that someone has used the old structure with the params keyword,
// those values will now be moved to the top level.
// This should be very unlikely as it would lead to constructs like .Params.params.foo,
// and most people see params as an Hugo internal keyword.
pcfg.Params = maps.ToStringMap(v)
case "_target", "target":
var target PageMatcher
if err := decodePageMatcher(v, &target); err != nil {
return pcfg, err
}
pcfg.Target = target
default:
// Legacy config.
if pcfg.Params == nil {
pcfg.Params = make(maps.Params)
}
pcfg.Params[k] = v
}
}
return pcfg, pcfg.init()
}
// decodePageMatcher decodes m into v.
func decodePageMatcher(m any, v *PageMatcher) error {
if err := mapstructure.WeakDecode(m, v); err != nil {
return err
}
@@ -140,3 +188,14 @@ func DecodePageMatcher(m any, v *PageMatcher) error {
return nil
}
type PageMatcherParamsConfig struct {
// Apply Params to all Pages matching Target.
Params maps.Params
Target PageMatcher
}
func (p *PageMatcherParamsConfig) init() error {
maps.PrepareParams(p.Params)
return nil
}