mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 14:02:09 -05:00
Support, but warn, about top level language custom params
Updates #10947
This commit is contained in:
parent
05542130ba
commit
7ce033a89d
4 changed files with 103 additions and 16 deletions
|
@ -70,7 +70,7 @@ func (p Params) IsZero() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range p {
|
for k := range p {
|
||||||
return k == mergeStrategyKey
|
return k == MergeStrategyKey
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -103,7 +103,7 @@ func (p Params) merge(ps ParamsMergeStrategy, pp Params) {
|
||||||
|
|
||||||
for k, v := range pp {
|
for k, v := range pp {
|
||||||
|
|
||||||
if k == mergeStrategyKey {
|
if k == MergeStrategyKey {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
vv, found := p[k]
|
vv, found := p[k]
|
||||||
|
@ -124,7 +124,7 @@ func (p Params) merge(ps ParamsMergeStrategy, pp Params) {
|
||||||
|
|
||||||
// For internal use.
|
// For internal use.
|
||||||
func (p Params) GetMergeStrategy() (ParamsMergeStrategy, bool) {
|
func (p Params) GetMergeStrategy() (ParamsMergeStrategy, bool) {
|
||||||
if v, found := p[mergeStrategyKey]; found {
|
if v, found := p[MergeStrategyKey]; found {
|
||||||
if s, ok := v.(ParamsMergeStrategy); ok {
|
if s, ok := v.(ParamsMergeStrategy); ok {
|
||||||
return s, true
|
return s, true
|
||||||
}
|
}
|
||||||
|
@ -134,8 +134,8 @@ func (p Params) GetMergeStrategy() (ParamsMergeStrategy, bool) {
|
||||||
|
|
||||||
// For internal use.
|
// For internal use.
|
||||||
func (p Params) DeleteMergeStrategy() bool {
|
func (p Params) DeleteMergeStrategy() bool {
|
||||||
if _, found := p[mergeStrategyKey]; found {
|
if _, found := p[MergeStrategyKey]; found {
|
||||||
delete(p, mergeStrategyKey)
|
delete(p, MergeStrategyKey)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -148,7 +148,7 @@ func (p Params) SetMergeStrategy(s ParamsMergeStrategy) {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("invalid merge strategy %q", s))
|
panic(fmt.Sprintf("invalid merge strategy %q", s))
|
||||||
}
|
}
|
||||||
p[mergeStrategyKey] = s
|
p[MergeStrategyKey] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNested(m map[string]any, indices []string) (any, string, map[string]any) {
|
func getNested(m map[string]any, indices []string) (any, string, map[string]any) {
|
||||||
|
@ -242,7 +242,7 @@ const (
|
||||||
// Add new keys, merge existing.
|
// Add new keys, merge existing.
|
||||||
ParamsMergeStrategyDeep ParamsMergeStrategy = "deep"
|
ParamsMergeStrategyDeep ParamsMergeStrategy = "deep"
|
||||||
|
|
||||||
mergeStrategyKey = "_merge"
|
MergeStrategyKey = "_merge"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CleanConfigStringMapString removes any processing instructions from m,
|
// CleanConfigStringMapString removes any processing instructions from m,
|
||||||
|
@ -251,13 +251,13 @@ func CleanConfigStringMapString(m map[string]string) map[string]string {
|
||||||
if m == nil || len(m) == 0 {
|
if m == nil || len(m) == 0 {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
if _, found := m[mergeStrategyKey]; !found {
|
if _, found := m[MergeStrategyKey]; !found {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
// Create a new map and copy all the keys except the merge strategy key.
|
// Create a new map and copy all the keys except the merge strategy key.
|
||||||
m2 := make(map[string]string, len(m)-1)
|
m2 := make(map[string]string, len(m)-1)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
if k != mergeStrategyKey {
|
if k != MergeStrategyKey {
|
||||||
m2[k] = v
|
m2[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,13 +270,13 @@ func CleanConfigStringMap(m map[string]any) map[string]any {
|
||||||
if m == nil || len(m) == 0 {
|
if m == nil || len(m) == 0 {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
if _, found := m[mergeStrategyKey]; !found {
|
if _, found := m[MergeStrategyKey]; !found {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
// Create a new map and copy all the keys except the merge strategy key.
|
// Create a new map and copy all the keys except the merge strategy key.
|
||||||
m2 := make(map[string]any, len(m)-1)
|
m2 := make(map[string]any, len(m)-1)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
if k != mergeStrategyKey {
|
if k != MergeStrategyKey {
|
||||||
m2[k] = v
|
m2[k] = v
|
||||||
}
|
}
|
||||||
switch v2 := v.(type) {
|
switch v2 := v.(type) {
|
||||||
|
@ -313,7 +313,7 @@ func PrepareParams(m Params) {
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
var retyped bool
|
var retyped bool
|
||||||
lKey := strings.ToLower(k)
|
lKey := strings.ToLower(k)
|
||||||
if lKey == mergeStrategyKey {
|
if lKey == MergeStrategyKey {
|
||||||
v = toMergeStrategy(v)
|
v = toMergeStrategy(v)
|
||||||
retyped = true
|
retyped = true
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -75,7 +75,7 @@ func TestParamsSetAndMerge(t *testing.T) {
|
||||||
|
|
||||||
createParamsPair := func() (Params, Params) {
|
createParamsPair := func() (Params, Params) {
|
||||||
p1 := Params{"a": "av", "c": "cv", "nested": Params{"al2": "al2v", "cl2": "cl2v"}}
|
p1 := Params{"a": "av", "c": "cv", "nested": Params{"al2": "al2v", "cl2": "cl2v"}}
|
||||||
p2 := Params{"b": "bv", "a": "abv", "nested": Params{"bl2": "bl2v", "al2": "al2bv"}, mergeStrategyKey: ParamsMergeStrategyDeep}
|
p2 := Params{"b": "bv", "a": "abv", "nested": Params{"bl2": "bl2v", "al2": "al2bv"}, MergeStrategyKey: ParamsMergeStrategyDeep}
|
||||||
return p1, p2
|
return p1, p2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func TestParamsSetAndMerge(t *testing.T) {
|
||||||
"bl2": "bl2v",
|
"bl2": "bl2v",
|
||||||
},
|
},
|
||||||
"b": "bv",
|
"b": "bv",
|
||||||
mergeStrategyKey: ParamsMergeStrategyDeep,
|
MergeStrategyKey: ParamsMergeStrategyDeep,
|
||||||
})
|
})
|
||||||
|
|
||||||
p1, p2 = createParamsPair()
|
p1, p2 = createParamsPair()
|
||||||
|
|
|
@ -63,6 +63,31 @@ type InternalConfig struct {
|
||||||
LiveReloadPort int
|
LiveReloadPort int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All non-params config keys for language.
|
||||||
|
var configLanguageKeys map[string]bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
skip := map[string]bool{
|
||||||
|
"internal": true,
|
||||||
|
"c": true,
|
||||||
|
"rootconfig": true,
|
||||||
|
}
|
||||||
|
configLanguageKeys = make(map[string]bool)
|
||||||
|
addKeys := func(v reflect.Value) {
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
name := strings.ToLower(v.Type().Field(i).Name)
|
||||||
|
if skip[name] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
configLanguageKeys[name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addKeys(reflect.ValueOf(Config{}))
|
||||||
|
addKeys(reflect.ValueOf(RootConfig{}))
|
||||||
|
addKeys(reflect.ValueOf(config.CommonDirs{}))
|
||||||
|
addKeys(reflect.ValueOf(langs.LanguageConfig{}))
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// For internal use only.
|
// For internal use only.
|
||||||
Internal InternalConfig `mapstructure:"-" json:"-"`
|
Internal InternalConfig `mapstructure:"-" json:"-"`
|
||||||
|
@ -328,7 +353,7 @@ type ConfigCompiled struct {
|
||||||
Clock time.Time
|
Clock time.Time
|
||||||
|
|
||||||
// This is set to the last transient error found during config compilation.
|
// This is set to the last transient error found during config compilation.
|
||||||
// With themes/modules we compule the configuration in multiple passes, and
|
// With themes/modules we compute the configuration in multiple passes, and
|
||||||
// errors with missing output format definitions may resolve itself.
|
// errors with missing output format definitions may resolve itself.
|
||||||
transientErr error
|
transientErr error
|
||||||
}
|
}
|
||||||
|
@ -659,7 +684,30 @@ func FromLoadConfigResult(fs afero.Fs, res config.LoadConfigResult) (*Configs, e
|
||||||
var differentRootKeys []string
|
var differentRootKeys []string
|
||||||
switch x := v.(type) {
|
switch x := v.(type) {
|
||||||
case maps.Params:
|
case maps.Params:
|
||||||
|
var params maps.Params
|
||||||
|
pv, found := x["params"]
|
||||||
|
if found {
|
||||||
|
params = pv.(maps.Params)
|
||||||
|
} else {
|
||||||
|
params = maps.Params{
|
||||||
|
maps.MergeStrategyKey: maps.ParamsMergeStrategyDeep,
|
||||||
|
}
|
||||||
|
x["params"] = params
|
||||||
|
}
|
||||||
|
|
||||||
for kk, vv := range x {
|
for kk, vv := range x {
|
||||||
|
if kk == "_merge" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if kk != maps.MergeStrategyKey && !configLanguageKeys[kk] {
|
||||||
|
// This should have been placed below params.
|
||||||
|
// We accidently allowed it in the past, so we need to support it a little longer,
|
||||||
|
// But log a warning.
|
||||||
|
if _, found := params[kk]; !found {
|
||||||
|
helpers.Deprecated(fmt.Sprintf("config: languages.%s.%s: custom params on the language top level", k, kk), fmt.Sprintf("Put the value below [languages.%s.params]. See See https://gohugo.io/content-management/multilingual/#changes-in-hugo-01120", k), false)
|
||||||
|
params[kk] = vv
|
||||||
|
}
|
||||||
|
}
|
||||||
if kk == "baseurl" {
|
if kk == "baseurl" {
|
||||||
// baseURL configure don the language level is a multihost setup.
|
// baseURL configure don the language level is a multihost setup.
|
||||||
isMultiHost = true
|
isMultiHost = true
|
||||||
|
|
|
@ -778,6 +778,43 @@ Home.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigParamSetOnLanguageLevel(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- hugo.toml --
|
||||||
|
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT"]
|
||||||
|
[languages]
|
||||||
|
[languages.en]
|
||||||
|
title = "English Title"
|
||||||
|
thisIsAParam = "thisIsAParamValue"
|
||||||
|
[languages.en.params]
|
||||||
|
myparam = "enParamValue"
|
||||||
|
[languages.sv]
|
||||||
|
title = "Svensk Title"
|
||||||
|
[languages.sv.params]
|
||||||
|
myparam = "svParamValue"
|
||||||
|
-- layouts/index.html --
|
||||||
|
MyParam: {{ site.Params.myparam }}
|
||||||
|
ThisIsAParam: {{ site.Params.thisIsAParam }}
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
b, err := NewIntegrationTestBuilder(
|
||||||
|
IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
},
|
||||||
|
).BuildE()
|
||||||
|
|
||||||
|
b.Assert(err, qt.IsNil)
|
||||||
|
b.AssertFileContent("public/index.html", `
|
||||||
|
MyParam: enParamValue
|
||||||
|
ThisIsAParam: thisIsAParamValue
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReproCommentsIn10947(t *testing.T) {
|
func TestReproCommentsIn10947(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -817,7 +854,9 @@ title: "My Swedish Section"
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
b.Assert(b.H.Log.LogCounters().WarnCounter.Count(), qt.Equals, uint64(2))
|
{
|
||||||
|
b.Assert(b.H.Log.LogCounters().WarnCounter.Count(), qt.Equals, uint64(2))
|
||||||
|
}
|
||||||
b.AssertFileContent("public/index.html", `
|
b.AssertFileContent("public/index.html", `
|
||||||
AllPages: 4|
|
AllPages: 4|
|
||||||
Sections: true|
|
Sections: true|
|
||||||
|
|
Loading…
Reference in a new issue