shithub: hugo

Download patch

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=",