hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 1fa2417777d82b81bf37919ad02de4f5dcbf0d50
parent bb549a0d57505a6b8f28930bb91a9ab44cbb3288
Author: Vas Sudanagunta <vas@commonkarma.org>
Date:   Sun, 11 Feb 2018 19:10:49 -0500

Add support for YAML array data files

* Unmarshaled YAML arrays indistinguishable from JSON arrays.
* Fixes #3890

Diffstat:
Mhugolib/datafiles_test.go | 60++++++++++++++++--------------------------------------------
Mhugolib/site.go | 2+-
Mparser/frontmatter.go | 17+++++++++++++++++
3 files changed, 34 insertions(+), 45 deletions(-)
diff --git a/hugolib/datafiles_test.go b/hugolib/datafiles_test.go
@@ -95,25 +95,23 @@ func TestDataDirBoolean(t *testing.T) {
 
 func TestDataDirTwoFiles(t *testing.T) {
 	t.Parallel()
-	equivDataDirs := make([]dataDir, 2)
+	equivDataDirs := make([]dataDir, 3)
 
 	equivDataDirs[0].addSource("data/test/foo.json", `{ "bar": "foofoo"  }`)
-	equivDataDirs[0].addSource("data/test.json", `{ "hello": [ { "world": "foo" } ] }`)
+	equivDataDirs[0].addSource("data/test.json", `{ "hello": [ "world", "foo" ] }`)
 
 	equivDataDirs[1].addSource("data/test/foo.yaml", "bar: foofoo")
-	equivDataDirs[1].addSource("data/test.yaml", "hello:\n- world: foo")
+	equivDataDirs[1].addSource("data/test.yaml", "hello:\n- world\n- foo")
 
-	// TODO Unresolved Issue #3890
-	/*
-		equivDataDirs[2].addSource("data/test/foo.toml", "bar = \"foofoo\"")
-		equivDataDirs[2].addSource("data/test.toml", "[[hello]]\nworld = \"foo\"")
-	*/
+	equivDataDirs[2].addSource("data/test/foo.toml", "bar = \"foofoo\"")
+	equivDataDirs[2].addSource("data/test.toml", "hello = [\"world\", \"foo\"]")
 
 	expected :=
 		map[string]interface{}{
 			"test": map[string]interface{}{
 				"hello": []interface{}{
-					map[string]interface{}{"world": "foo"},
+					"world",
+					"foo",
 				},
 				"foo": map[string]interface{}{
 					"bar": "foofoo",
@@ -156,54 +154,28 @@ func TestDataDirOverriddenValue(t *testing.T) {
 	doTestEquivalentDataDirs(t, equivDataDirs, expected)
 }
 
-// Issue #4361
-func TestDataDirJSONArrayAtTopLevelOfFile(t *testing.T) {
-	t.Parallel()
-
-	var dd dataDir
-	dd.addSource("data/test.json", `[ { "hello": "world" }, { "what": "time" }, { "is": "lunch?" } ]`)
-
-	expected :=
-		map[string]interface{}{
-			"test": []interface{}{
-				map[string]interface{}{"hello": "world"},
-				map[string]interface{}{"what": "time"},
-				map[string]interface{}{"is": "lunch?"},
-			},
-		}
-
-	doTestDataDir(t, dd, expected)
-}
-
-// TODO Issue #3890 unresolved
-func TestDataDirYAMLArrayAtTopLevelOfFile(t *testing.T) {
+// Issue #4361, #3890
+func TestDataDirArrayAtTopLevelOfFile(t *testing.T) {
 	t.Parallel()
+	equivDataDirs := make([]dataDir, 2)
 
-	var dd dataDir
-	dd.addSource("data/test.yaml", `
+	equivDataDirs[0].addSource("data/test.json", `[ { "hello": "world" }, { "what": "time" }, { "is": "lunch?" } ]`)
+	equivDataDirs[1].addSource("data/test.yaml", `
 - hello: world
 - what: time
 - is: lunch?
 `)
 
-	//TODO decide whether desired structure map[interface {}]interface{} as shown
-	// and as the YAML parser produces, or should it be map[string]interface{}
-	// all the way down per Issue #4138
 	expected :=
 		map[string]interface{}{
 			"test": []interface{}{
-				map[interface{}]interface{}{"hello": "world"},
-				map[interface{}]interface{}{"what": "time"},
-				map[interface{}]interface{}{"is": "lunch?"},
+				map[string]interface{}{"hello": "world"},
+				map[string]interface{}{"what": "time"},
+				map[string]interface{}{"is": "lunch?"},
 			},
 		}
 
-	// what we are actually getting as of v0.34
-	expectedV0_34 :=
-		map[string]interface{}{}
-	_ = expected
-
-	doTestDataDir(t, dd, expectedV0_34)
+	doTestEquivalentDataDirs(t, equivDataDirs, expected)
 }
 
 // Issue #892
diff --git a/hugolib/site.go b/hugolib/site.go
@@ -870,7 +870,7 @@ func (s *Site) readData(f source.ReadableFile) (interface{}, error) {
 
 	switch f.Extension() {
 	case "yaml", "yml":
-		return parser.HandleYAMLMetaData(content)
+		return parser.HandleYAMLData(content)
 	case "json":
 		return parser.HandleJSONData(content)
 	case "toml":
diff --git a/parser/frontmatter.go b/parser/frontmatter.go
@@ -216,6 +216,23 @@ func HandleYAMLMetaData(datum []byte) (map[string]interface{}, error) {
 	return m, err
 }
 
+// HandleYAMLData unmarshals YAML-encoded datum and returns a Go interface
+// representing the encoded data structure.
+func HandleYAMLData(datum []byte) (interface{}, error) {
+	var m interface{}
+	err := yaml.Unmarshal(datum, &m)
+
+	// To support boolean keys, the `yaml` package unmarshals maps to
+	// map[interface{}]interface{}. Here we recurse through the result
+	// and change all maps to map[string]interface{} like we would've
+	// gotten from `json`.
+	if err == nil {
+		m = stringifyYAMLMapKeys(m)
+	}
+
+	return m, err
+}
+
 // stringifyKeysMapValue recurses into in and changes all instances of
 // map[interface{}]interface{} to map[string]interface{}. This is useful to
 // work around the impedence mismatch between JSON and YAML unmarshaling that's