ref: 773812de6f8870c7ce0355bfafd71d1959a8c199
parent: 4c7e119ca195085c81b5bb3c51dee6409b15ec98
author: Erlend Klakegg Bergheim <[email protected]>
date: Tue Jan 20 18:08:01 EST 2015
Reads data files inside data/ and makes data available in .Site.Data Fixes #476. Conflicts: hugolib/site.go
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -119,6 +119,7 @@
viper.SetDefault("StaticDir", "static")
viper.SetDefault("ArchetypeDir", "archetypes")
viper.SetDefault("PublishDir", "public")
+ viper.SetDefault("DataDir", "data")
viper.SetDefault("DefaultLayout", "post")
viper.SetDefault("BuildDrafts", false)
viper.SetDefault("BuildFuture", false)
@@ -287,6 +288,7 @@
return nil
}
+ filepath.Walk(helpers.AbsPathify(viper.GetString("DataDir")), walker)
filepath.Walk(helpers.AbsPathify(viper.GetString("ContentDir")), walker)
filepath.Walk(helpers.AbsPathify(viper.GetString("LayoutDir")), walker)
filepath.Walk(helpers.AbsPathify(viper.GetString("StaticDir")), walker)
--- a/commands/new.go
+++ b/commands/new.go
@@ -130,6 +130,7 @@
mkdir(createpath, "content")
mkdir(createpath, "archetypes")
mkdir(createpath, "static")
+ mkdir(createpath, "data")
createConfig(createpath, configFormat)
}
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -34,6 +34,7 @@
bp "github.com/spf13/hugo/bufferpool"
"github.com/spf13/hugo/helpers"
"github.com/spf13/hugo/hugofs"
+ "github.com/spf13/hugo/parser"
"github.com/spf13/hugo/source"
"github.com/spf13/hugo/target"
"github.com/spf13/hugo/tpl"
@@ -81,6 +82,7 @@
params map[string]interface{}
draftCount int
futureCount int
+ Data map[string]interface{}
}
type targetList struct {
@@ -112,6 +114,7 @@
BuildDrafts bool
canonifyUrls bool
paginationPageCount uint64
+ Data *map[string]interface{}
}
// SiteSocial is a place to put social details on a site level. These are the
@@ -264,6 +267,61 @@
return s.Tmpl.AddTemplate(name, data)
}
+func (s *Site) loadData(fs source.Input) (err error) {
+ s.Data = make(map[string]interface{})
+
+ for _, r := range fs.Files() {
+ // Crawl in data tree to insert data
+ var current map[string]interface{}
+ current = s.Data
+ for _, key := range strings.Split(r.Dir(), string(os.PathSeparator)) {
+ if key != "" {
+ if _, ok := current[key]; !ok {
+ current[key] = make(map[string]interface{})
+ }
+ current = current[key].(map[string]interface{})
+ }
+ }
+
+ // Read data file
+ data, err := readFile(r)
+ if err != nil {
+ return err
+ }
+
+ // Copy content from current to data when needed
+ if _, ok := current[r.BaseFileName()]; ok {
+ data := data.(map[string]interface{})
+
+ for key, value := range current[r.BaseFileName()].(map[string]interface{}) {
+ if _, override := data[key]; override {
+ return errors.New("Data in " + r.Path() + " is overrided in subfolder.")
+ } else {
+ data[key] = value
+ }
+ }
+ }
+
+ // Insert data
+ current[r.BaseFileName()] = data
+ }
+
+ return
+}
+
+func readFile(f *source.File) (interface{}, error) {
+ switch f.Extension() {
+ case "yaml", "yml":
+ return parser.HandleYamlMetaData(f.Bytes())
+ case "json":
+ return parser.HandleJsonMetaData(f.Bytes())
+ case "toml":
+ return parser.HandleTomlMetaData(f.Bytes())
+ default:
+ return nil, errors.New("Not supported for data: " + f.Extension())
+ }
+}
+
func (s *Site) Process() (err error) {
if err = s.initialize(); err != nil {
return
@@ -270,6 +328,10 @@
}
s.prepTemplates()
s.Tmpl.PrintErrors()
+ if err = s.loadData(&source.Filesystem{Base: s.absDataDir()}); err != nil {
+ return
+ }
+ s.timerStep("load data")
s.timerStep("initialize & template prep")
if err = s.CreatePages(); err != nil {
return
@@ -379,11 +441,16 @@
Menus: &s.Menus,
Params: params,
Permalinks: permalinks,
+ Data: &s.Data,
}
}
func (s *Site) hasTheme() bool {
return viper.GetString("theme") != ""
+}
+
+func (s *Site) absDataDir() string {
+ return helpers.AbsPathify(viper.GetString("DataDir"))
}
func (s *Site) absThemeDir() string {
--- a/hugolib/site_test.go
+++ b/hugolib/site_test.go
@@ -5,6 +5,7 @@
"fmt"
"html/template"
"io"
+ "os"
"path/filepath"
"strings"
"testing"
@@ -743,5 +744,20 @@
if s.Taxonomies["categories"]["e"][0].Page.Title != "bza" {
t.Errorf("Pages in unexpected order, 'bza' expected first, got '%v'", s.Taxonomies["categories"]["e"][0].Page.Title)
+ }
+}
+
+func TestDataDir(t *testing.T) {
+ sources := []source.ByteSource{
+ {filepath.FromSlash("test" + string(os.PathSeparator) + "foo.yaml"), []byte("bar: foofoo")},
+ {filepath.FromSlash("test.yaml"), []byte("hello:\n- world: foo")},
+ }
+
+ s := &Site{}
+ s.loadData(&source.InMemorySource{ByteSource: sources})
+
+ expected := "map[test:map[hello:[map[world:foo]] foo:map[bar:foofoo]]]"
+ if fmt.Sprint(s.Data) != expected {
+ t.Errorf("Expected structure '%s', got '%s'", expected, s.Data)
}
}