ref: 40b1b8f70373dacf2458fbd9a67be32fc6830f91
parent: 4d6cd3cb2aa46df781adde8debf9f64d50973365
author: Bjørn Erik Pedersen <[email protected]>
date: Sun Oct 16 15:28:21 EDT 2016
Fix case issue Viper vs Blackfriday config There are still work to be done in the case department, but that will have to be another day. Fixes #2581 See https://github.com/spf13/viper/issues/261
--- a/helpers/content.go
+++ b/helpers/content.go
@@ -27,7 +27,6 @@
"github.com/miekg/mmark"
"github.com/mitchellh/mapstructure"
"github.com/russross/blackfriday"
- "github.com/spf13/cast"
bp "github.com/spf13/hugo/bufferpool"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
@@ -60,7 +59,8 @@
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
func NewBlackfriday(c ConfigProvider) *Blackfriday {
- combinedParam := map[string]interface{}{
+
+ defaultParam := map[string]interface{}{
"smartypants": true,
"angledQuotes": false,
"fractions": true,
@@ -73,17 +73,24 @@
"sourceRelativeLinksProjectFolder": "/docs/content",
}
+ ToLowerMap(defaultParam)
+
siteParam := c.GetStringMap("blackfriday")
- if siteParam != nil {
- siteConfig := cast.ToStringMap(siteParam)
- for key, value := range siteConfig {
- combinedParam[key] = value
+ siteConfig := make(map[string]interface{})
+
+ for k, v := range defaultParam {
+ siteConfig[k] = v
+ }
+
+ if siteParam != nil {
+ for k, v := range siteParam {
+ siteConfig[k] = v
}
}
combinedConfig := &Blackfriday{}
- if err := mapstructure.Decode(combinedParam, combinedConfig); err != nil {
+ if err := mapstructure.Decode(siteConfig, combinedConfig); err != nil {
jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error())
}
--- a/helpers/general.go
+++ b/helpers/general.go
@@ -119,6 +119,29 @@
return bc
}
+// ToLowerMap makes all the keys in the given map lower cased and will do so
+// recursively.
+// Notes:
+// * This will modify the map given.
+// * Any nested map[interface{}]interface{} will be converted to map[string]interface{}.
+func ToLowerMap(m map[string]interface{}) {
+ for k, v := range m {
+ switch v.(type) {
+ case map[interface{}]interface{}:
+ v = cast.ToStringMap(v)
+ ToLowerMap(v.(map[string]interface{}))
+ case map[string]interface{}:
+ ToLowerMap(v.(map[string]interface{}))
+ }
+
+ lKey := strings.ToLower(k)
+ if k != lKey {
+ delete(m, k)
+ }
+ m[lKey] = v
+ }
+}
+
// ReaderToString is the same as ReaderToBytes, but returns a string.
func ReaderToString(lines io.Reader) string {
if lines == nil {
--- a/helpers/general_test.go
+++ b/helpers/general_test.go
@@ -291,3 +291,56 @@
}
}
}
+
+func TestToLowerMap(t *testing.T) {
+
+ tests := []struct {
+ input map[string]interface{}
+ expected map[string]interface{}
+ }{
+ {
+ map[string]interface{}{
+ "abC": 32,
+ },
+ map[string]interface{}{
+ "abc": 32,
+ },
+ },
+ {
+ map[string]interface{}{
+ "abC": 32,
+ "deF": map[interface{}]interface{}{
+ 23: "A value",
+ 24: map[string]interface{}{
+ "AbCDe": "A value",
+ "eFgHi": "Another value",
+ },
+ },
+ "gHi": map[string]interface{}{
+ "J": 25,
+ },
+ },
+ map[string]interface{}{
+ "abc": 32,
+ "def": map[string]interface{}{
+ "23": "A value",
+ "24": map[string]interface{}{
+ "abcde": "A value",
+ "efghi": "Another value",
+ },
+ },
+ "ghi": map[string]interface{}{
+ "j": 25,
+ },
+ },
+ },
+ }
+
+ for i, test := range tests {
+ // ToLowerMap modifies input.
+ ToLowerMap(test.input)
+ if !reflect.DeepEqual(test.expected, test.input) {
+ t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, test.input)
+ }
+ }
+}
--- a/hugolib/multilingual.go
+++ b/hugolib/multilingual.go
@@ -17,7 +17,6 @@
"sync"
"sort"
- "strings"
"errors"
"fmt"
@@ -84,6 +83,7 @@
for lang, langConf := range l {
langsMap, err := cast.ToStringMapE(langConf)
+ helpers.ToLowerMap(langsMap)
if err != nil {
return nil, fmt.Errorf("Language config is not a map: %T", langConf)
@@ -91,8 +91,7 @@
language := helpers.NewLanguage(lang)
- for k, v := range langsMap {
- loki := strings.ToLower(k)
+ for loki, v := range langsMap {
switch loki {
case "title":
language.Title = cast.ToString(v)
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -392,9 +392,11 @@
panic(fmt.Sprintf("nil language for %s with source lang %s", p.BaseFileName(), p.lang))
}
p.renderingConfig = helpers.NewBlackfriday(p.Language())
+
if err := mapstructure.Decode(pageParam, p.renderingConfig); err != nil {
jww.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
}
+
})
return p.renderingConfig
--- a/hugolib/site_test.go
+++ b/hugolib/site_test.go
@@ -337,8 +337,9 @@
viper.Set("DisableRSS", false)
viper.Set("RSSUri", "index.xml")
viper.Set("blackfriday",
+ // TODO(bep) https://github.com/spf13/viper/issues/261
map[string]interface{}{
- "plainIDAnchors": true})
+ strings.ToLower("plainIDAnchors"): true})
viper.Set("UglyURLs", uglyURLs)
@@ -964,8 +965,9 @@
viper.Set("PluralizeListTitles", false)
viper.Set("CanonifyURLs", false)
viper.Set("blackfriday",
+ // TODO(bep) see https://github.com/spf13/viper/issues/261
map[string]interface{}{
- "sourceRelativeLinksProjectFolder": "/docs"})
+ strings.ToLower("sourceRelativeLinksProjectFolder"): "/docs"})
site := &Site{
Source: &source.InMemorySource{ByteSource: sources},
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -299,10 +299,10 @@
"revisionTime": "2016-10-06T16:53:40Z"
},
{
- "checksumSHA1": "+RJudGkFugn3gRJYUIan1Wbugdw=",
+ "checksumSHA1": "2EeKIC5kUssQK8g49DOa78FoMgs=",
"path": "github.com/spf13/viper",
- "revision": "51f23d1f1c56a7773ae8f2cfd038f7996ecc9ac2",
- "revisionTime": "2016-10-10T11:40:38Z"
+ "revision": "50515b700e02658272117a72bd641b6b7f1222e5",
+ "revisionTime": "2016-10-14T09:24:45Z"
},
{
"checksumSHA1": "Q2V7Zs3diLmLfmfbiuLpSxETSuY=",