Fix case issue Viper vs Blackfriday config
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 16 Oct 2016 17:28:21 +0000 (19:28 +0200)
committerGitHub <noreply@github.com>
Sun, 16 Oct 2016 17:28:21 +0000 (19:28 +0200)
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

helpers/content.go
helpers/general.go
helpers/general_test.go
hugolib/multilingual.go
hugolib/page.go
hugolib/site_test.go
vendor/vendor.json

index 516fc72b975d53b6fa1616578c458263707383c4..aa1327d7422e96425a23ee42bab1c433f23e76c0 100644 (file)
@@ -27,7 +27,6 @@ import (
        "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 @@ type Blackfriday struct {
 
 // 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 @@ func NewBlackfriday(c ConfigProvider) *Blackfriday {
                "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())
        }
 
index b420bfa2cf0cfdf862c8bfad4305610f035981c9..ba828ed8cec4e1c5a925f7829f4b5a09aacb3685 100644 (file)
@@ -119,6 +119,29 @@ func ReaderToBytes(lines io.Reader) []byte {
        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 {
index 089bb9b1a274e60781793b61362613bdc91c384c..8afdb59eb4163446177b0182211ad0c2ed0c9ff1 100644 (file)
@@ -291,3 +291,56 @@ func TestDoArithmetic(t *testing.T) {
                }
        }
 }
+
+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)
+               }
+       }
+}
index 2b0214e10c0396ffcfa5de8a963905ef645c44a9..cf45e723344d5ea65f41ea15e75461ed65410015 100644 (file)
@@ -17,7 +17,6 @@ import (
        "sync"
 
        "sort"
-       "strings"
 
        "errors"
        "fmt"
@@ -84,6 +83,7 @@ func toSortedLanguages(l map[string]interface{}) (helpers.Languages, error) {
 
        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 @@ func toSortedLanguages(l map[string]interface{}) (helpers.Languages, error) {
 
                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)
index d2205e32ff6851f5b4d2e9f79531655cc79f8f31..99ef6e41368fdc830a22b2ae10f9bbf985708b20 100644 (file)
@@ -392,9 +392,11 @@ func (p *Page) getRenderingConfig() *helpers.Blackfriday {
                        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
index b278456fca0a235c9b30f1c6bbcc32f9414d49cd..9cf094e19525fca765f32c3899218eb34769e76d 100644 (file)
@@ -337,8 +337,9 @@ func doTestShouldAlwaysHaveUglyURLs(t *testing.T, uglyURLs bool) {
        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 @@ func setupLinkingMockSite(t *testing.T) *Site {
        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},
index 04ff19b06fc464f3fae298c2ff6f9f28c0524c35..c4208e0e0e63d3db4c6881e82c17e6285b381391 100644 (file)
                        "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=",