ref: 773812de6f8870c7ce0355bfafd71d1959a8c199
parent: 4c7e119ca195085c81b5bb3c51dee6409b15ec98
author: Erlend Klakegg Bergheim <erlend@klakegg.net>
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)}
}
--
⑨