github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/config/allconfig/alldecoders.go (about) 1 // Copyright 2023 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package allconfig 15 16 import ( 17 "fmt" 18 "strings" 19 20 "github.com/gohugoio/hugo/cache/filecache" 21 "github.com/gohugoio/hugo/common/maps" 22 "github.com/gohugoio/hugo/common/types" 23 "github.com/gohugoio/hugo/config" 24 "github.com/gohugoio/hugo/config/privacy" 25 "github.com/gohugoio/hugo/config/security" 26 "github.com/gohugoio/hugo/config/services" 27 "github.com/gohugoio/hugo/deploy" 28 "github.com/gohugoio/hugo/langs" 29 "github.com/gohugoio/hugo/markup/markup_config" 30 "github.com/gohugoio/hugo/media" 31 "github.com/gohugoio/hugo/minifiers" 32 "github.com/gohugoio/hugo/modules" 33 "github.com/gohugoio/hugo/navigation" 34 "github.com/gohugoio/hugo/output" 35 "github.com/gohugoio/hugo/related" 36 "github.com/gohugoio/hugo/resources/images" 37 "github.com/gohugoio/hugo/resources/page" 38 "github.com/gohugoio/hugo/resources/page/pagemeta" 39 "github.com/mitchellh/mapstructure" 40 "github.com/spf13/afero" 41 "github.com/spf13/cast" 42 ) 43 44 type decodeConfig struct { 45 p config.Provider 46 c *Config 47 fs afero.Fs 48 bcfg config.BaseConfig 49 } 50 51 type decodeWeight struct { 52 key string 53 decode func(decodeWeight, decodeConfig) error 54 getCompiler func(c *Config) configCompiler 55 weight int 56 internalOrDeprecated bool // Hide it from the docs. 57 } 58 59 var allDecoderSetups = map[string]decodeWeight{ 60 "": { 61 key: "", 62 weight: -100, // Always first. 63 decode: func(d decodeWeight, p decodeConfig) error { 64 if err := mapstructure.WeakDecode(p.p.Get(""), &p.c.RootConfig); err != nil { 65 return err 66 } 67 68 // This need to match with Lang which is always lower case. 69 p.c.RootConfig.DefaultContentLanguage = strings.ToLower(p.c.RootConfig.DefaultContentLanguage) 70 71 return nil 72 }, 73 }, 74 "imaging": { 75 key: "imaging", 76 decode: func(d decodeWeight, p decodeConfig) error { 77 var err error 78 p.c.Imaging, err = images.DecodeConfig(p.p.GetStringMap(d.key)) 79 return err 80 }, 81 }, 82 "caches": { 83 key: "caches", 84 decode: func(d decodeWeight, p decodeConfig) error { 85 var err error 86 p.c.Caches, err = filecache.DecodeConfig(p.fs, p.bcfg, p.p.GetStringMap(d.key)) 87 if p.c.IgnoreCache { 88 // Set MaxAge in all caches to 0. 89 for k, cache := range p.c.Caches { 90 cache.MaxAge = 0 91 p.c.Caches[k] = cache 92 } 93 } 94 return err 95 }, 96 }, 97 "build": { 98 key: "build", 99 decode: func(d decodeWeight, p decodeConfig) error { 100 p.c.Build = config.DecodeBuildConfig(p.p) 101 return nil 102 }, 103 getCompiler: func(c *Config) configCompiler { 104 return &c.Build 105 }, 106 }, 107 "frontmatter": { 108 key: "frontmatter", 109 decode: func(d decodeWeight, p decodeConfig) error { 110 var err error 111 p.c.Frontmatter, err = pagemeta.DecodeFrontMatterConfig(p.p) 112 return err 113 }, 114 }, 115 "markup": { 116 key: "markup", 117 decode: func(d decodeWeight, p decodeConfig) error { 118 var err error 119 p.c.Markup, err = markup_config.Decode(p.p) 120 return err 121 }, 122 }, 123 "server": { 124 key: "server", 125 decode: func(d decodeWeight, p decodeConfig) error { 126 var err error 127 p.c.Server, err = config.DecodeServer(p.p) 128 return err 129 }, 130 getCompiler: func(c *Config) configCompiler { 131 return &c.Server 132 }, 133 }, 134 "minify": { 135 key: "minify", 136 decode: func(d decodeWeight, p decodeConfig) error { 137 var err error 138 p.c.Minify, err = minifiers.DecodeConfig(p.p.Get(d.key)) 139 return err 140 }, 141 }, 142 "mediatypes": { 143 key: "mediatypes", 144 decode: func(d decodeWeight, p decodeConfig) error { 145 var err error 146 p.c.MediaTypes, err = media.DecodeTypes(p.p.GetStringMap(d.key)) 147 return err 148 }, 149 }, 150 "outputs": { 151 key: "outputs", 152 decode: func(d decodeWeight, p decodeConfig) error { 153 defaults := createDefaultOutputFormats(p.c.OutputFormats.Config) 154 m := maps.CleanConfigStringMap(p.p.GetStringMap("outputs")) 155 p.c.Outputs = make(map[string][]string) 156 for k, v := range m { 157 s := types.ToStringSlicePreserveString(v) 158 for i, v := range s { 159 s[i] = strings.ToLower(v) 160 } 161 p.c.Outputs[k] = s 162 } 163 // Apply defaults. 164 for k, v := range defaults { 165 if _, found := p.c.Outputs[k]; !found { 166 p.c.Outputs[k] = v 167 } 168 } 169 return nil 170 }, 171 }, 172 "outputformats": { 173 key: "outputformats", 174 decode: func(d decodeWeight, p decodeConfig) error { 175 var err error 176 p.c.OutputFormats, err = output.DecodeConfig(p.c.MediaTypes.Config, p.p.Get(d.key)) 177 return err 178 }, 179 }, 180 "params": { 181 key: "params", 182 decode: func(d decodeWeight, p decodeConfig) error { 183 p.c.Params = maps.CleanConfigStringMap(p.p.GetStringMap("params")) 184 if p.c.Params == nil { 185 p.c.Params = make(map[string]any) 186 } 187 188 // Before Hugo 0.112.0 this was configured via site Params. 189 if mainSections, found := p.c.Params["mainsections"]; found { 190 p.c.MainSections = types.ToStringSlicePreserveString(mainSections) 191 if p.c.MainSections == nil { 192 p.c.MainSections = []string{} 193 } 194 } 195 196 return nil 197 }, 198 }, 199 "module": { 200 key: "module", 201 decode: func(d decodeWeight, p decodeConfig) error { 202 var err error 203 p.c.Module, err = modules.DecodeConfig(p.p) 204 return err 205 }, 206 }, 207 "permalinks": { 208 key: "permalinks", 209 decode: func(d decodeWeight, p decodeConfig) error { 210 var err error 211 p.c.Permalinks, err = page.DecodePermalinksConfig(p.p.GetStringMap(d.key)) 212 return err 213 }, 214 }, 215 "sitemap": { 216 key: "sitemap", 217 decode: func(d decodeWeight, p decodeConfig) error { 218 var err error 219 p.c.Sitemap, err = config.DecodeSitemap(config.SitemapConfig{Priority: -1, Filename: "sitemap.xml"}, p.p.GetStringMap(d.key)) 220 return err 221 }, 222 }, 223 "taxonomies": { 224 key: "taxonomies", 225 decode: func(d decodeWeight, p decodeConfig) error { 226 p.c.Taxonomies = maps.CleanConfigStringMapString(p.p.GetStringMapString(d.key)) 227 return nil 228 }, 229 }, 230 "related": { 231 key: "related", 232 weight: 100, // This needs to be decoded after taxonomies. 233 decode: func(d decodeWeight, p decodeConfig) error { 234 if p.p.IsSet(d.key) { 235 var err error 236 p.c.Related, err = related.DecodeConfig(p.p.GetParams(d.key)) 237 if err != nil { 238 return fmt.Errorf("failed to decode related config: %w", err) 239 } 240 } else { 241 p.c.Related = related.DefaultConfig 242 if _, found := p.c.Taxonomies["tag"]; found { 243 p.c.Related.Add(related.IndexConfig{Name: "tags", Weight: 80, Type: related.TypeBasic}) 244 } 245 } 246 return nil 247 }, 248 }, 249 "languages": { 250 key: "languages", 251 decode: func(d decodeWeight, p decodeConfig) error { 252 var err error 253 m := p.p.GetStringMap(d.key) 254 if len(m) == 1 { 255 // In v0.112.4 we moved this to the language config, but it's very commmon for mono language sites to have this at the top level. 256 var first maps.Params 257 var ok bool 258 for _, v := range m { 259 first, ok = v.(maps.Params) 260 if ok { 261 break 262 } 263 } 264 if first != nil { 265 if _, found := first["languagecode"]; !found { 266 first["languagecode"] = p.p.GetString("languagecode") 267 } 268 } 269 } 270 p.c.Languages, err = langs.DecodeConfig(m) 271 if err != nil { 272 return err 273 } 274 275 // Validate defaultContentLanguage. 276 var found bool 277 for lang := range p.c.Languages { 278 if lang == p.c.DefaultContentLanguage { 279 found = true 280 break 281 } 282 } 283 if !found { 284 return fmt.Errorf("config value %q for defaultContentLanguage does not match any language definition", p.c.DefaultContentLanguage) 285 } 286 287 return nil 288 }, 289 }, 290 "cascade": { 291 key: "cascade", 292 decode: func(d decodeWeight, p decodeConfig) error { 293 var err error 294 p.c.Cascade, err = page.DecodeCascadeConfig(p.p.Get(d.key)) 295 return err 296 }, 297 }, 298 "menus": { 299 key: "menus", 300 decode: func(d decodeWeight, p decodeConfig) error { 301 var err error 302 p.c.Menus, err = navigation.DecodeConfig(p.p.Get(d.key)) 303 return err 304 }, 305 }, 306 "privacy": { 307 key: "privacy", 308 decode: func(d decodeWeight, p decodeConfig) error { 309 var err error 310 p.c.Privacy, err = privacy.DecodeConfig(p.p) 311 return err 312 }, 313 }, 314 "security": { 315 key: "security", 316 decode: func(d decodeWeight, p decodeConfig) error { 317 var err error 318 p.c.Security, err = security.DecodeConfig(p.p) 319 return err 320 }, 321 }, 322 "services": { 323 key: "services", 324 decode: func(d decodeWeight, p decodeConfig) error { 325 var err error 326 p.c.Services, err = services.DecodeConfig(p.p) 327 return err 328 }, 329 }, 330 "deployment": { 331 key: "deployment", 332 decode: func(d decodeWeight, p decodeConfig) error { 333 var err error 334 p.c.Deployment, err = deploy.DecodeConfig(p.p) 335 return err 336 }, 337 }, 338 "author": { 339 key: "author", 340 decode: func(d decodeWeight, p decodeConfig) error { 341 p.c.Author = maps.CleanConfigStringMap(p.p.GetStringMap(d.key)) 342 return nil 343 }, 344 internalOrDeprecated: true, 345 }, 346 "social": { 347 key: "social", 348 decode: func(d decodeWeight, p decodeConfig) error { 349 p.c.Social = maps.CleanConfigStringMapString(p.p.GetStringMapString(d.key)) 350 return nil 351 }, 352 internalOrDeprecated: true, 353 }, 354 "uglyurls": { 355 key: "uglyurls", 356 decode: func(d decodeWeight, p decodeConfig) error { 357 v := p.p.Get(d.key) 358 switch vv := v.(type) { 359 case bool: 360 p.c.UglyURLs = vv 361 case string: 362 p.c.UglyURLs = vv == "true" 363 default: 364 p.c.UglyURLs = cast.ToStringMapBool(v) 365 } 366 return nil 367 }, 368 internalOrDeprecated: true, 369 }, 370 "internal": { 371 key: "internal", 372 decode: func(d decodeWeight, p decodeConfig) error { 373 return mapstructure.WeakDecode(p.p.GetStringMap(d.key), &p.c.Internal) 374 }, 375 internalOrDeprecated: true, 376 }, 377 } 378 379 func init() { 380 for k, v := range allDecoderSetups { 381 // Verify that k and v.key is all lower case. 382 if k != strings.ToLower(k) { 383 panic(fmt.Sprintf("key %q is not lower case", k)) 384 } 385 if v.key != strings.ToLower(v.key) { 386 panic(fmt.Sprintf("key %q is not lower case", v.key)) 387 } 388 389 if k != v.key { 390 panic(fmt.Sprintf("key %q is not the same as the map key %q", k, v.key)) 391 } 392 } 393 }