summaryrefslogtreecommitdiffstats
path: root/hugolib
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2016-08-06 14:51:50 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2016-09-06 18:32:17 +0300
commit596e0e98e4483d2a0a709412a338ceddb6538757 (patch)
tree0f8b33f98aa67dcb6fed48095b47ddd565575960 /hugolib
parent7cac19b1e3d2631395b88998b523a5a6d84b9e29 (diff)
Make it possible to add a language in server mode
See #2309
Diffstat (limited to 'hugolib')
-rw-r--r--hugolib/hugo_sites.go91
-rw-r--r--hugolib/hugo_sites_test.go120
-rw-r--r--hugolib/multilingual.go21
-rw-r--r--hugolib/node.go3
4 files changed, 183 insertions, 52 deletions
diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go
index 93ffc53da..b41334fdc 100644
--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -40,24 +40,25 @@ type HugoSites struct {
// NewHugoSites creates a new collection of sites given the input sites, building
// a language configuration based on those.
func NewHugoSites(sites ...*Site) (*HugoSites, error) {
- languages := make(Languages, len(sites))
- for i, s := range sites {
- if s.Language == nil {
- return nil, errors.New("Missing language for site")
- }
- languages[i] = s.Language
- }
- defaultLang := viper.GetString("DefaultContentLanguage")
- if defaultLang == "" {
- defaultLang = "en"
+ langConfig, err := newMultiLingualFromSites(sites...)
+
+ if err != nil {
+ return nil, err
}
- langConfig := &Multilingual{Languages: languages, DefaultLang: NewLanguage(defaultLang)}
return &HugoSites{Multilingual: langConfig, Sites: sites}, nil
}
// NewHugoSitesFromConfiguration creates HugoSites from the global Viper config.
func NewHugoSitesFromConfiguration() (*HugoSites, error) {
+ sites, err := createSitesFromConfig()
+ if err != nil {
+ return nil, err
+ }
+ return NewHugoSites(sites...)
+}
+
+func createSitesFromConfig() ([]*Site, error) {
var sites []*Site
multilingual := viper.GetStringMap("Languages")
if len(multilingual) == 0 {
@@ -80,19 +81,43 @@ func NewHugoSitesFromConfiguration() (*HugoSites, error) {
}
- return NewHugoSites(sites...)
-
+ return sites, nil
}
// Reset resets the sites, making it ready for a full rebuild.
// TODO(bep) multilingo
-func (h HugoSites) Reset() {
+func (h *HugoSites) reset() {
for i, s := range h.Sites {
h.Sites[i] = s.Reset()
}
}
-func (h HugoSites) toSiteInfos() []*SiteInfo {
+func (h *HugoSites) reCreateFromConfig() error {
+ oldSite := h.Sites[0]
+ sites, err := createSitesFromConfig()
+
+ if err != nil {
+ return err
+ }
+
+ langConfig, err := newMultiLingualFromSites(sites...)
+
+ if err != nil {
+ return err
+ }
+
+ h.Sites = sites
+ h.Multilingual = langConfig
+
+ for _, s := range h.Sites {
+ // TODO(bep) ml Tmpl
+ s.Tmpl = oldSite.Tmpl
+ }
+
+ return nil
+}
+
+func (h *HugoSites) toSiteInfos() []*SiteInfo {
infos := make([]*SiteInfo, len(h.Sites))
for i, s := range h.Sites {
infos[i] = &s.Info
@@ -106,6 +131,11 @@ type BuildCfg struct {
Watching bool
// Print build stats at the end of a build
PrintStats bool
+ // Reset site state before build. Use to force full rebuilds.
+ ResetState bool
+ // Re-creates the sites from configuration before a build.
+ // This is needed if new languages are added.
+ CreateSitesFromConfig bool
// Skip rendering. Useful for testing.
SkipRender bool
// Use this to add templates to use for rendering.
@@ -114,13 +144,19 @@ type BuildCfg struct {
}
// Build builds all sites.
-func (h HugoSites) Build(config BuildCfg) error {
+func (h *HugoSites) Build(config BuildCfg) error {
- if h.Sites == nil || len(h.Sites) == 0 {
- return errors.New("No site(s) to build")
+ t0 := time.Now()
+
+ if config.ResetState {
+ h.reset()
}
- t0 := time.Now()
+ if config.CreateSitesFromConfig {
+ if err := h.reCreateFromConfig(); err != nil {
+ return err
+ }
+ }
// We should probably refactor the Site and pull up most of the logic from there to here,
// but that seems like a daunting task.
@@ -143,6 +179,7 @@ func (h HugoSites) Build(config BuildCfg) error {
if len(h.Sites) > 1 {
// Initialize the rest
for _, site := range h.Sites[1:] {
+ // TODO(bep) ml Tmpl
site.Tmpl = firstSite.Tmpl
site.initializeSiteInfo()
}
@@ -184,9 +221,23 @@ func (h HugoSites) Build(config BuildCfg) error {
}
// Rebuild rebuilds all sites.
-func (h HugoSites) Rebuild(config BuildCfg, events ...fsnotify.Event) error {
+func (h *HugoSites) Rebuild(config BuildCfg, events ...fsnotify.Event) error {
t0 := time.Now()
+ if config.CreateSitesFromConfig {
+ return errors.New("Rebuild does not support 'CreateSitesFromConfig'. Use Build.")
+ }
+
+ if config.ResetState {
+ return errors.New("Rebuild does not support 'ResetState'. Use Build.")
+ }
+
+ for _, s := range h.Sites {
+ // TODO(bep) ml
+ s.Multilingual = h.Multilingual
+ s.RunMode.Watching = config.Watching
+ }
+
firstSite := h.Sites[0]
for _, s := range h.Sites {
diff --git a/hugolib/hugo_sites_test.go b/hugolib/hugo_sites_test.go
index cc8a02993..158b65124 100644
--- a/hugolib/hugo_sites_test.go
+++ b/hugolib/hugo_sites_test.go
@@ -39,7 +39,7 @@ func testCommonResetState() {
func TestMultiSitesBuild(t *testing.T) {
testCommonResetState()
- sites := createMultiTestSites(t)
+ sites := createMultiTestSites(t, multiSiteTomlConfig)
err := sites.Build(BuildCfg{})
@@ -141,7 +141,7 @@ func TestMultiSitesBuild(t *testing.T) {
func TestMultiSitesRebuild(t *testing.T) {
testCommonResetState()
- sites := createMultiTestSites(t)
+ sites := createMultiTestSites(t, multiSiteTomlConfig)
cfg := BuildCfg{}
err := sites.Build(cfg)
@@ -299,10 +299,95 @@ func TestMultiSitesRebuild(t *testing.T) {
this.assertFunc(t)
}
+}
+
+func TestAddNewLanguage(t *testing.T) {
+ testCommonResetState()
+
+ sites := createMultiTestSites(t, multiSiteTomlConfig)
+ cfg := BuildCfg{}
+
+ err := sites.Build(cfg)
+
+ if err != nil {
+ t.Fatalf("Failed to build sites: %s", err)
+ }
+
+ newConfig := multiSiteTomlConfig + `
+
+[Languages.no]
+weight = 15
+title = "Norsk"
+`
+
+ writeNewContentFile(t, "Norwegian Contentfile", "2016-01-01", "content/sect/doc1.no.md", 10)
+ // replace the config
+ writeSource(t, "multilangconfig.toml", newConfig)
+
+ // Watching does not work with in-memory fs, so we trigger a reload manually
+ require.NoError(t, viper.ReadInConfig())
+
+ err = sites.Build(BuildCfg{CreateSitesFromConfig: true})
+
+ if err != nil {
+ t.Fatalf("Failed to rebuild sites: %s", err)
+ }
+
+ require.Len(t, sites.Sites, 3, fmt.Sprintf("Len %d", len(sites.Sites)))
+
+ // The Norwegian site should be put in the middle (language weight=15)
+ enSite := sites.Sites[0]
+ noSite := sites.Sites[1]
+ frSite := sites.Sites[2]
+ require.True(t, enSite.Language.Lang == "en", enSite.Language.Lang)
+ require.True(t, noSite.Language.Lang == "no", noSite.Language.Lang)
+ require.True(t, frSite.Language.Lang == "fr", frSite.Language.Lang)
+
+ require.Len(t, enSite.Pages, 3)
+ require.Len(t, frSite.Pages, 3)
+
+ // Veriy Norwegian site
+ require.Len(t, noSite.Pages, 1)
+ noPage := noSite.Pages[0]
+ require.Equal(t, "Norwegian Contentfile", noPage.Title)
+ require.Equal(t, "no", noPage.Lang())
+ require.Len(t, noPage.Translations(), 2)
+ require.Len(t, noPage.AllTranslations(), 3)
+ require.Equal(t, "en", noPage.Translations()[0].Lang())
+ //noFile := readDestination(t, "/public/no/doc1/index.html")
+ //require.True(t, strings.Contains("foo", noFile), noFile)
}
-func createMultiTestSites(t *testing.T) *HugoSites {
+var multiSiteTomlConfig = `
+DefaultExtension = "html"
+baseurl = "http://example.com/blog"
+DisableSitemap = false
+DisableRSS = false
+RSSUri = "index.xml"
+
+paginate = 2
+DefaultContentLanguage = "fr"
+
+[permalinks]
+ other = "/somewhere/else/:filename"
+
+[Taxonomies]
+tag = "tags"
+
+[Languages]
+[Languages.en]
+weight = 10
+title = "English"
+
+[Languages.fr]
+weight = 20
+title = "Français"
+[Languages.fr.Taxonomies]
+plaque = "plaques"
+`
+
+func createMultiTestSites(t *testing.T, tomlConfig string) *HugoSites {
// Add some layouts
if err := afero.WriteFile(hugofs.Source(),
@@ -445,35 +530,6 @@ draft: true
`)},
}
- tomlConfig := `
-DefaultExtension = "html"
-baseurl = "http://example.com/blog"
-DisableSitemap = false
-DisableRSS = false
-RSSUri = "index.xml"
-
-paginate = 2
-DefaultContentLanguage = "fr"
-
-
-[permalinks]
- other = "/somewhere/else/:filename"
-
-[Taxonomies]
-tag = "tags"
-
-[Languages]
-[Languages.en]
-weight = 1
-title = "English"
-
-[Languages.fr]
-weight = 2
-title = "Français"
-[Languages.fr.Taxonomies]
-plaque = "plaques"
-`
-
writeSource(t, "multilangconfig.toml", tomlConfig)
if err := LoadGlobalConfig("", "multilangconfig.toml"); err != nil {
t.Fatalf("Failed to load config: %s", err)
diff --git a/hugolib/multilingual.go b/hugolib/multilingual.go
index 8bc7bea33..cc9f607f2 100644
--- a/hugolib/multilingual.go
+++ b/hugolib/multilingual.go
@@ -6,6 +6,7 @@ import (
"sort"
"strings"
+ "errors"
"fmt"
"github.com/spf13/cast"
@@ -63,6 +64,26 @@ func (ml *Multilingual) Language(lang string) *Language {
return ml.langMap[lang]
}
+func newMultiLingualFromSites(sites ...*Site) (*Multilingual, error) {
+ languages := make(Languages, len(sites))
+
+ for i, s := range sites {
+ if s.Language == nil {
+ return nil, errors.New("Missing language for site")
+ }
+ languages[i] = s.Language
+ }
+
+ defaultLang := viper.GetString("DefaultContentLanguage")
+
+ if defaultLang == "" {
+ defaultLang = "en"
+ }
+
+ return &Multilingual{Languages: languages, DefaultLang: NewLanguage(defaultLang)}, nil
+
+}
+
func (ml *Multilingual) enabled() bool {
return len(ml.Languages) > 1
}
diff --git a/hugolib/node.go b/hugolib/node.go
index 2d07e426b..db1d16631 100644
--- a/hugolib/node.go
+++ b/hugolib/node.go
@@ -195,6 +195,9 @@ func (n *Node) Language() *Language {
}
func (n *Node) Lang() string {
+ // When set, Language can be different from lang in the case where there is a
+ // content file (doc.sv.md) with language indicator, but there is no language
+ // config for that language. Then the language will fall back on the site default.
if n.Language() != nil {
return n.Language().Lang
}