mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
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
This commit is contained in:
parent
4d6cd3cb2a
commit
40b1b8f703
7 changed files with 102 additions and 16 deletions
|
@ -27,7 +27,6 @@ import (
|
||||||
"github.com/miekg/mmark"
|
"github.com/miekg/mmark"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/russross/blackfriday"
|
"github.com/russross/blackfriday"
|
||||||
"github.com/spf13/cast"
|
|
||||||
bp "github.com/spf13/hugo/bufferpool"
|
bp "github.com/spf13/hugo/bufferpool"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -60,7 +59,8 @@ type Blackfriday struct {
|
||||||
|
|
||||||
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
|
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
|
||||||
func NewBlackfriday(c ConfigProvider) *Blackfriday {
|
func NewBlackfriday(c ConfigProvider) *Blackfriday {
|
||||||
combinedParam := map[string]interface{}{
|
|
||||||
|
defaultParam := map[string]interface{}{
|
||||||
"smartypants": true,
|
"smartypants": true,
|
||||||
"angledQuotes": false,
|
"angledQuotes": false,
|
||||||
"fractions": true,
|
"fractions": true,
|
||||||
|
@ -73,17 +73,24 @@ func NewBlackfriday(c ConfigProvider) *Blackfriday {
|
||||||
"sourceRelativeLinksProjectFolder": "/docs/content",
|
"sourceRelativeLinksProjectFolder": "/docs/content",
|
||||||
}
|
}
|
||||||
|
|
||||||
siteParam := c.GetStringMap("blackfriday")
|
ToLowerMap(defaultParam)
|
||||||
if siteParam != nil {
|
|
||||||
siteConfig := cast.ToStringMap(siteParam)
|
|
||||||
|
|
||||||
for key, value := range siteConfig {
|
siteParam := c.GetStringMap("blackfriday")
|
||||||
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{}
|
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())
|
jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,29 @@ func ReaderToBytes(lines io.Reader) []byte {
|
||||||
return bc
|
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.
|
// ReaderToString is the same as ReaderToBytes, but returns a string.
|
||||||
func ReaderToString(lines io.Reader) string {
|
func ReaderToString(lines io.Reader) string {
|
||||||
if lines == nil {
|
if lines == nil {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -84,6 +83,7 @@ func toSortedLanguages(l map[string]interface{}) (helpers.Languages, error) {
|
||||||
|
|
||||||
for lang, langConf := range l {
|
for lang, langConf := range l {
|
||||||
langsMap, err := cast.ToStringMapE(langConf)
|
langsMap, err := cast.ToStringMapE(langConf)
|
||||||
|
helpers.ToLowerMap(langsMap)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Language config is not a map: %T", langConf)
|
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)
|
language := helpers.NewLanguage(lang)
|
||||||
|
|
||||||
for k, v := range langsMap {
|
for loki, v := range langsMap {
|
||||||
loki := strings.ToLower(k)
|
|
||||||
switch loki {
|
switch loki {
|
||||||
case "title":
|
case "title":
|
||||||
language.Title = cast.ToString(v)
|
language.Title = cast.ToString(v)
|
||||||
|
|
|
@ -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))
|
panic(fmt.Sprintf("nil language for %s with source lang %s", p.BaseFileName(), p.lang))
|
||||||
}
|
}
|
||||||
p.renderingConfig = helpers.NewBlackfriday(p.Language())
|
p.renderingConfig = helpers.NewBlackfriday(p.Language())
|
||||||
|
|
||||||
if err := mapstructure.Decode(pageParam, p.renderingConfig); err != nil {
|
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())
|
jww.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return p.renderingConfig
|
return p.renderingConfig
|
||||||
|
|
|
@ -337,8 +337,9 @@ func doTestShouldAlwaysHaveUglyURLs(t *testing.T, uglyURLs bool) {
|
||||||
viper.Set("DisableRSS", false)
|
viper.Set("DisableRSS", false)
|
||||||
viper.Set("RSSUri", "index.xml")
|
viper.Set("RSSUri", "index.xml")
|
||||||
viper.Set("blackfriday",
|
viper.Set("blackfriday",
|
||||||
|
// TODO(bep) https://github.com/spf13/viper/issues/261
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"plainIDAnchors": true})
|
strings.ToLower("plainIDAnchors"): true})
|
||||||
|
|
||||||
viper.Set("UglyURLs", uglyURLs)
|
viper.Set("UglyURLs", uglyURLs)
|
||||||
|
|
||||||
|
@ -964,8 +965,9 @@ func setupLinkingMockSite(t *testing.T) *Site {
|
||||||
viper.Set("PluralizeListTitles", false)
|
viper.Set("PluralizeListTitles", false)
|
||||||
viper.Set("CanonifyURLs", false)
|
viper.Set("CanonifyURLs", false)
|
||||||
viper.Set("blackfriday",
|
viper.Set("blackfriday",
|
||||||
|
// TODO(bep) see https://github.com/spf13/viper/issues/261
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"sourceRelativeLinksProjectFolder": "/docs"})
|
strings.ToLower("sourceRelativeLinksProjectFolder"): "/docs"})
|
||||||
|
|
||||||
site := &Site{
|
site := &Site{
|
||||||
Source: &source.InMemorySource{ByteSource: sources},
|
Source: &source.InMemorySource{ByteSource: sources},
|
||||||
|
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -299,10 +299,10 @@
|
||||||
"revisionTime": "2016-10-06T16:53:40Z"
|
"revisionTime": "2016-10-06T16:53:40Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "+RJudGkFugn3gRJYUIan1Wbugdw=",
|
"checksumSHA1": "2EeKIC5kUssQK8g49DOa78FoMgs=",
|
||||||
"path": "github.com/spf13/viper",
|
"path": "github.com/spf13/viper",
|
||||||
"revision": "51f23d1f1c56a7773ae8f2cfd038f7996ecc9ac2",
|
"revision": "50515b700e02658272117a72bd641b6b7f1222e5",
|
||||||
"revisionTime": "2016-10-10T11:40:38Z"
|
"revisionTime": "2016-10-14T09:24:45Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Q2V7Zs3diLmLfmfbiuLpSxETSuY=",
|
"checksumSHA1": "Q2V7Zs3diLmLfmfbiuLpSxETSuY=",
|
||||||
|
|
Loading…
Reference in a new issue