Fix language menu config regression

Fixes #8672
This commit is contained in:
Bjørn Erik Pedersen 2021-06-22 18:17:49 +02:00
parent 4a9d408fe0
commit 093dacab29
4 changed files with 135 additions and 20 deletions

View file

@ -197,6 +197,12 @@ func (c *defaultConfigProvider) Merge(k string, v interface{}) {
defer c.mu.Unlock() defer c.mu.Unlock()
k = strings.ToLower(k) k = strings.ToLower(k)
const (
languagesKey = "languages"
paramsKey = "params"
menusKey = "menus"
)
if k == "" { if k == "" {
rs, f := c.root.GetMergeStrategy() rs, f := c.root.GetMergeStrategy()
if f && rs == maps.ParamsMergeStrategyNone { if f && rs == maps.ParamsMergeStrategyNone {
@ -210,8 +216,44 @@ func (c *defaultConfigProvider) Merge(k string, v interface{}) {
// those as a special case. // those as a special case.
for kk, vv := range p { for kk, vv := range p {
if pp, ok := vv.(maps.Params); ok { if pp, ok := vv.(maps.Params); ok {
if ppp, ok := c.root[kk]; ok { if pppi, ok := c.root[kk]; ok {
ppp.(maps.Params).Merge(pp) ppp := pppi.(maps.Params)
if kk == languagesKey {
// Languages is currently a special case.
// We may have languages with menus or params in the
// right map that is not present in the left map.
// With the default merge strategy those items will not
// be passed over.
var hasParams, hasMenus bool
for _, rv := range pp {
if lkp, ok := rv.(maps.Params); ok {
_, hasMenus = lkp[menusKey]
_, hasParams = lkp[paramsKey]
}
}
if hasMenus || hasParams {
for _, lv := range ppp {
if lkp, ok := lv.(maps.Params); ok {
if hasMenus {
if _, ok := lkp[menusKey]; !ok {
p := maps.Params{}
p.SetDefaultMergeStrategy(maps.ParamsMergeStrategyShallow)
lkp[menusKey] = p
}
}
if hasParams {
if _, ok := lkp[paramsKey]; !ok {
p := maps.Params{}
p.SetDefaultMergeStrategy(maps.ParamsMergeStrategyShallow)
lkp[paramsKey] = p
}
}
}
}
}
}
ppp.Merge(pp)
} else { } else {
// We need to use the default merge strategy for // We need to use the default merge strategy for
// this key. // this key.

View file

@ -93,20 +93,6 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid
} }
} }
// TODO(bep) improve this. This is currently needed to get the merge correctly.
if l.cfg.IsSet("languages") {
langs := l.cfg.GetParams("languages")
for _, lang := range langs {
langp := lang.(maps.Params)
if _, ok := langp["menus"]; !ok {
langp["menus"] = make(maps.Params)
}
if _, ok := langp["params"]; !ok {
langp["params"] = make(maps.Params)
}
}
}
l.cfg.SetDefaultMergeStrategy() l.cfg.SetDefaultMergeStrategy()
// We create languages based on the settings, so we need to make sure that // We create languages based on the settings, so we need to make sure that

View file

@ -76,7 +76,7 @@ func TestLoadMultiConfig(t *testing.T) {
c.Assert(cfg.GetString("DontChange"), qt.Equals, "same") c.Assert(cfg.GetString("DontChange"), qt.Equals, "same")
} }
func TestLoadConfigFromTheme(t *testing.T) { func TestLoadConfigFromThemes(t *testing.T) {
t.Parallel() t.Parallel()
c := qt.New(t) c := qt.New(t)
@ -185,11 +185,15 @@ name = "menu-theme"
` `
buildForStrategy := func(t testing.TB, s string) *sitesBuilder { buildForConfig := func(mainConfig, themeConfig string) *sitesBuilder {
mainConfig := strings.ReplaceAll(mainConfigTemplate, "MERGE_PARAMS", s)
b := newTestSitesBuilder(t) b := newTestSitesBuilder(t)
b.WithConfigFile("toml", mainConfig).WithThemeConfigFile("toml", themeConfig) b.WithConfigFile("toml", mainConfig).WithThemeConfigFile("toml", themeConfig)
return b.CreateSites().Build(BuildCfg{}) return b.Build(BuildCfg{})
}
buildForStrategy := func(t testing.TB, s string) *sitesBuilder {
mainConfig := strings.ReplaceAll(mainConfigTemplate, "MERGE_PARAMS", s)
return buildForConfig(mainConfig, themeConfig)
} }
c.Run("Merge default", func(c *qt.C) { c.Run("Merge default", func(c *qt.C) {
@ -316,6 +320,64 @@ name = "menu-theme"
}) })
}) })
c.Run("Merge no params in project", func(c *qt.C) {
b := buildForConfig(
"baseURL=\"https://example.org\"\ntheme = \"test-theme\"\n",
"[params]\np1 = \"p1 theme\"\n",
)
got := b.Cfg.Get("").(maps.Params)
b.Assert(got["params"], qt.DeepEquals, maps.Params{
"p1": "p1 theme",
})
})
c.Run("Merge language no menus or params in project", func(c *qt.C) {
b := buildForConfig(
`
theme = "test-theme"
baseURL = "https://example.com/"
[languages]
[languages.en]
languageName = "English"
`,
`
[languages]
[languages.en]
languageName = "EnglishTheme"
[languages.en.params]
p1="themep1"
[[languages.en.menus.main]]
name = "menu-theme"
`,
)
got := b.Cfg.Get("").(maps.Params)
b.Assert(got["languages"], qt.DeepEquals,
maps.Params{
"en": maps.Params{
"languagename": "English",
"menus": maps.Params{
"main": []map[string]interface{}{
{
"name": "menu-theme",
},
},
},
"params": maps.Params{
"p1": "themep1",
},
},
},
)
})
} }
func TestLoadConfigFromThemeDir(t *testing.T) { func TestLoadConfigFromThemeDir(t *testing.T) {

View file

@ -54,3 +54,28 @@ weight = 1
b.AssertFileContent("public/index.html", "Hello: Hello") b.AssertFileContent("public/index.html", "Hello: Hello")
}) })
} }
func TestLanguageBugs(t *testing.T) {
c := qt.New(t)
// Issue #8672
c.Run("Config with language, menu in root only", func(c *qt.C) {
b := newTestSitesBuilder(c)
b.WithConfigFile("toml", `
theme = "test-theme"
[[menus.foo]]
name = "foo-a"
[languages.en]
`,
)
b.WithThemeConfigFile("toml", `[languages.en]`)
b.Build(BuildCfg{})
menus := b.H.Sites[0].Menus()
c.Assert(menus, qt.HasLen, 1)
})
}