diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-03-21 17:21:46 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-04-02 08:06:21 +0200 |
commit | eb42774e587816b1fbcafbcea59ed65df703882a (patch) | |
tree | fdb62cf17355b47fa485941f3c3fffd604896daa /hugolib | |
parent | f27977809ce5d5dce4db41db6323a4ad1b095985 (diff) |
Add support for a content dir set per language
A sample config:
```toml
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = true
[Languages]
[Languages.en]
weight = 10
title = "In English"
languageName = "English"
contentDir = "content/english"
[Languages.nn]
weight = 20
title = "På Norsk"
languageName = "Norsk"
contentDir = "content/norwegian"
```
The value of `contentDir` can be any valid path, even absolute path references. The only restriction is that the content dirs cannot overlap.
The content files will be assigned a language by
1. The placement: `content/norwegian/post/my-post.md` will be read as Norwegian content.
2. The filename: `content/english/post/my-post.nn.md` will be read as Norwegian even if it lives in the English content folder.
The content directories will be merged into a big virtual filesystem with one simple rule: The most specific language file will win.
This means that if both `content/norwegian/post/my-post.md` and `content/english/post/my-post.nn.md` exists, they will be considered duplicates and the version inside `content/norwegian` will win.
Note that translations will be automatically assigned by Hugo by the content file's relative placement, so `content/norwegian/post/my-post.md` will be a translation of `content/english/post/my-post.md`.
If this does not work for you, you can connect the translations together by setting a `translationKey` in the content files' front matter.
Fixes #4523
Fixes #4552
Fixes #4553
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/config.go | 8 | ||||
-rw-r--r-- | hugolib/disableKinds_test.go | 4 | ||||
-rw-r--r-- | hugolib/fileInfo.go | 19 | ||||
-rw-r--r-- | hugolib/fileInfo_test.go | 61 | ||||
-rw-r--r-- | hugolib/hugo_sites.go | 78 | ||||
-rw-r--r-- | hugolib/hugo_sites_build_test.go | 52 | ||||
-rw-r--r-- | hugolib/language_content_dir_test.go | 253 | ||||
-rw-r--r-- | hugolib/menu_test.go | 4 | ||||
-rw-r--r-- | hugolib/multilingual.go | 4 | ||||
-rw-r--r-- | hugolib/page.go | 22 | ||||
-rw-r--r-- | hugolib/page_bundler.go | 28 | ||||
-rw-r--r-- | hugolib/page_bundler_capture.go | 185 | ||||
-rw-r--r-- | hugolib/page_bundler_capture_test.go | 53 | ||||
-rw-r--r-- | hugolib/page_bundler_handlers.go | 9 | ||||
-rw-r--r-- | hugolib/page_bundler_test.go | 42 | ||||
-rw-r--r-- | hugolib/page_collections.go | 5 | ||||
-rw-r--r-- | hugolib/page_test.go | 54 | ||||
-rw-r--r-- | hugolib/prune_resources.go | 10 | ||||
-rw-r--r-- | hugolib/site.go | 21 | ||||
-rw-r--r-- | hugolib/site_url_test.go | 2 | ||||
-rw-r--r-- | hugolib/taxonomy_test.go | 4 | ||||
-rw-r--r-- | hugolib/testhelpers_test.go | 23 |
22 files changed, 602 insertions, 339 deletions
diff --git a/hugolib/config.go b/hugolib/config.go index 6eca1a969..9f206bc77 100644 --- a/hugolib/config.go +++ b/hugolib/config.go @@ -130,21 +130,17 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error } else { languages = make(map[string]interface{}) for k, v := range languagesFromConfig { - isDisabled := false for _, disabled := range disableLanguages { if disabled == defaultLang { return fmt.Errorf("cannot disable default language %q", defaultLang) } if strings.EqualFold(k, disabled) { - isDisabled = true + v.(map[string]interface{})["disabled"] = true break } } - if !isDisabled { - languages[k] = v - } - + languages[k] = v } } diff --git a/hugolib/disableKinds_test.go b/hugolib/disableKinds_test.go index d689f9dcc..edada1419 100644 --- a/hugolib/disableKinds_test.go +++ b/hugolib/disableKinds_test.go @@ -104,8 +104,8 @@ categories: writeSource(t, fs, "content/sect/p1.md", fmt.Sprintf(pageTemplate, "P1", "- tag1")) - writeNewContentFile(t, fs, "Category Terms", "2017-01-01", "content/categories/_index.md", 10) - writeNewContentFile(t, fs, "Tag1 List", "2017-01-01", "content/tags/tag1/_index.md", 10) + writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10) + writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/tag1/_index.md", 10) h, err := NewHugoSites(deps.DepsCfg{Fs: fs, Cfg: cfg}) diff --git a/hugolib/fileInfo.go b/hugolib/fileInfo.go index f819f6bfc..90cf91377 100644 --- a/hugolib/fileInfo.go +++ b/hugolib/fileInfo.go @@ -14,7 +14,6 @@ package hugolib import ( - "os" "strings" "github.com/gohugoio/hugo/helpers" @@ -25,11 +24,22 @@ import ( var ( _ source.File = (*fileInfo)(nil) _ source.ReadableFile = (*fileInfo)(nil) + _ pathLangFile = (*fileInfo)(nil) ) +// A partial interface to prevent ambigous compiler error. +type basePather interface { + Filename() string + RealName() string + BaseDir() string +} + type fileInfo struct { bundleTp bundleDirType + source.ReadableFile + basePather + overriddenLang string // Set if the content language for this file is disabled. @@ -43,6 +53,10 @@ func (fi *fileInfo) Lang() string { return fi.ReadableFile.Lang() } +func (fi *fileInfo) Filename() string { + return fi.basePather.Filename() +} + func (fi *fileInfo) isOwner() bool { return fi.bundleTp > bundleNot } @@ -55,12 +69,13 @@ func (fi *fileInfo) isContentFile() bool { return contentFileExtensionsSet[fi.Ext()] } -func newFileInfo(sp *source.SourceSpec, baseDir, filename string, fi os.FileInfo, tp bundleDirType) *fileInfo { +func newFileInfo(sp *source.SourceSpec, baseDir, filename string, fi pathLangFileFi, tp bundleDirType) *fileInfo { baseFi := sp.NewFileInfo(baseDir, filename, tp == bundleLeaf, fi) f := &fileInfo{ bundleTp: tp, ReadableFile: baseFi, + basePather: fi, } lang := f.Lang() diff --git a/hugolib/fileInfo_test.go b/hugolib/fileInfo_test.go deleted file mode 100644 index 18579c078..000000000 --- a/hugolib/fileInfo_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2017-present The Hugo Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package hugolib - -import ( - "testing" - - "path/filepath" - - "github.com/gohugoio/hugo/source" - "github.com/stretchr/testify/require" -) - -func TestBundleFileInfo(t *testing.T) { - t.Parallel() - - assert := require.New(t) - cfg, fs := newTestBundleSourcesMultilingual(t) - sourceSpec := source.NewSourceSpec(cfg, fs) - - for _, this := range []struct { - filename string - check func(f *fileInfo) - }{ - {"/path/to/file.md", func(fi *fileInfo) { - assert.Equal("md", fi.Ext()) - assert.Equal("en", fi.Lang()) - assert.False(fi.isOwner()) - assert.True(fi.isContentFile()) - }}, - {"/path/to/file.JPG", func(fi *fileInfo) { - assert.Equal("jpg", fi.Ext()) - assert.False(fi.isContentFile()) - }}, - {"/path/to/file.nn.png", func(fi *fileInfo) { - assert.Equal("png", fi.Ext()) - assert.Equal("nn", fi.Lang()) - assert.Equal("file", fi.TranslationBaseName()) - assert.False(fi.isContentFile()) - }}, - } { - fi := newFileInfo( - sourceSpec, - filepath.FromSlash("/work/base"), - filepath.FromSlash(this.filename), - nil, bundleNot) - this.check(fi) - } - -} diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index 4e802270d..f0eb21dc1 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -75,19 +75,8 @@ func (h *HugoSites) langSite() map[string]*Site { // GetContentPage finds a Page with content given the absolute filename. // Returns nil if none found. func (h *HugoSites) GetContentPage(filename string) *Page { - s := h.Sites[0] - contendDir := filepath.Join(s.PathSpec.AbsPathify(s.Cfg.GetString("contentDir"))) - if !strings.HasPrefix(filename, contendDir) { - return nil - } - - rel := strings.TrimPrefix(filename, contendDir) - rel = strings.TrimPrefix(rel, helpers.FilePathSeparator) - for _, s := range h.Sites { - - pos := s.rawAllPages.findPagePosByFilePath(rel) - + pos := s.rawAllPages.findPagePosByFilename(filename) if pos == -1 { continue } @@ -95,19 +84,16 @@ func (h *HugoSites) GetContentPage(filename string) *Page { } // If not found already, this may be bundled in another content file. - rel = filepath.Dir(rel) - for _, s := range h.Sites { - - pos := s.rawAllPages.findFirstPagePosByFilePathPrefix(rel) + dir := filepath.Dir(filename) + for _, s := range h.Sites { + pos := s.rawAllPages.findPagePosByFilnamePrefix(dir) if pos == -1 { continue } return s.rawAllPages[pos] } - return nil - } // NewHugoSites creates a new collection of sites given the input sites, building @@ -126,18 +112,11 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) { var contentChangeTracker *contentChangeMap - // Only needed in server mode. - // TODO(bep) clean up the running vs watching terms - if cfg.Running { - contentChangeTracker = &contentChangeMap{symContent: make(map[string]map[string]bool)} - } - h := &HugoSites{ - running: cfg.Running, - multilingual: langConfig, - multihost: cfg.Cfg.GetBool("multihost"), - ContentChanges: contentChangeTracker, - Sites: sites} + running: cfg.Running, + multilingual: langConfig, + multihost: cfg.Cfg.GetBool("multihost"), + Sites: sites} for _, s := range sites { s.owner = h @@ -149,6 +128,13 @@ func newHugoSites(cfg deps.DepsCfg, sites ...*Site) (*HugoSites, error) { h.Deps = sites[0].Deps + // Only needed in server mode. + // TODO(bep) clean up the running vs watching terms + if cfg.Running { + contentChangeTracker = &contentChangeMap{pathSpec: h.PathSpec, symContent: make(map[string]map[string]bool)} + h.ContentChanges = contentChangeTracker + } + if err := h.initGitInfo(); err != nil { return nil, err } @@ -212,6 +198,7 @@ func applyDepsIfNeeded(cfg deps.DepsCfg, sites ...*Site) error { d.OutputFormatsConfig = s.outputFormatsConfig s.Deps = d } + s.resourceSpec, err = resource.NewSpec(s.Deps.PathSpec, s.mediaTypesConfig) if err != nil { return err @@ -260,6 +247,9 @@ func createSitesFromConfig(cfg deps.DepsCfg) ([]*Site, error) { languages := getLanguages(cfg.Cfg) for _, lang := range languages { + if lang.Disabled { + continue + } var s *Site var err error cfg.Language = lang @@ -517,9 +507,9 @@ func (h *HugoSites) createMissingPages() error { return nil } -func (h *HugoSites) removePageByPath(path string) { +func (h *HugoSites) removePageByFilename(filename string) { for _, s := range h.Sites { - s.removePageByPath(path) + s.removePageFilename(filename) } } @@ -671,6 +661,8 @@ type contentChangeMap struct { branches []string leafs []string + pathSpec *helpers.PathSpec + // Hugo supports symlinked content (both directories and files). This // can lead to situations where the same file can be referenced from several // locations in /content -- which is really cool, but also means we have to @@ -683,7 +675,7 @@ type contentChangeMap struct { func (m *contentChangeMap) add(filename string, tp bundleDirType) { m.mu.Lock() - dir := filepath.Dir(filename) + dir := filepath.Dir(filename) + helpers.FilePathSeparator switch tp { case bundleBranch: m.branches = append(m.branches, dir) @@ -698,7 +690,7 @@ func (m *contentChangeMap) add(filename string, tp bundleDirType) { // Track the addition of bundle dirs. func (m *contentChangeMap) handleBundles(b *bundleDirs) { for _, bd := range b.bundles { - m.add(bd.fi.Filename(), bd.tp) + m.add(bd.fi.Path(), bd.tp) } } @@ -709,21 +701,21 @@ func (m *contentChangeMap) resolveAndRemove(filename string) (string, string, bu m.mu.RLock() defer m.mu.RUnlock() - dir, name := filepath.Split(filename) - dir = strings.TrimSuffix(dir, helpers.FilePathSeparator) - fileTp, isContent := classifyBundledFile(name) - - // If the file itself is a bundle, no need to look further: - if fileTp > bundleNot { - return dir, dir, fileTp + // Bundles share resources, so we need to start from the virtual root. + relPath, _ := m.pathSpec.RelContentDir(filename) + dir, name := filepath.Split(relPath) + if !strings.HasSuffix(dir, helpers.FilePathSeparator) { + dir += helpers.FilePathSeparator } + fileTp, _ := classifyBundledFile(name) + // This may be a member of a bundle. Start with branch bundles, the most specific. - if !isContent { + if fileTp != bundleLeaf { for i, b := range m.branches { if b == dir { m.branches = append(m.branches[:i], m.branches[i+1:]...) - return dir, dir, bundleBranch + return dir, b, bundleBranch } } } @@ -732,7 +724,7 @@ func (m *contentChangeMap) resolveAndRemove(filename string) (string, string, bu for i, l := range m.leafs { if strings.HasPrefix(dir, l) { m.leafs = append(m.leafs[:i], m.leafs[i+1:]...) - return dir, dir, bundleLeaf + return dir, l, bundleLeaf } } diff --git a/hugolib/hugo_sites_build_test.go b/hugolib/hugo_sites_build_test.go index 5e4f171da..1626fadcf 100644 --- a/hugolib/hugo_sites_build_test.go +++ b/hugolib/hugo_sites_build_test.go @@ -3,6 +3,7 @@ package hugolib import ( "bytes" "fmt" + "io" "strings" "testing" @@ -433,7 +434,7 @@ func TestMultiSitesRebuild(t *testing.T) { // t.Parallel() not supported, see https://github.com/fortytw2/leaktest/issues/4 // This leaktest seems to be a little bit shaky on Travis. if !isCI() { - defer leaktest.CheckTimeout(t, 30*time.Second)() + defer leaktest.CheckTimeout(t, 10*time.Second)() } assert := require.New(t) @@ -459,6 +460,8 @@ func TestMultiSitesRebuild(t *testing.T) { b.AssertFileContent("public/fr/sect/doc1/index.html", "Single", "Shortcode: Bonjour") b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Shortcode: Hello") + contentFs := b.H.BaseFs.ContentFs + for i, this := range []struct { preFunc func(t *testing.T) events []fsnotify.Event @@ -490,9 +493,9 @@ func TestMultiSitesRebuild(t *testing.T) { }, { func(t *testing.T) { - writeNewContentFile(t, fs, "new_en_1", "2016-07-31", "content/new1.en.md", -5) - writeNewContentFile(t, fs, "new_en_2", "1989-07-30", "content/new2.en.md", -10) - writeNewContentFile(t, fs, "new_fr_1", "2016-07-30", "content/new1.fr.md", 10) + writeNewContentFile(t, contentFs, "new_en_1", "2016-07-31", "new1.en.md", -5) + writeNewContentFile(t, contentFs, "new_en_2", "1989-07-30", "new2.en.md", -10) + writeNewContentFile(t, contentFs, "new_fr_1", "2016-07-30", "new1.fr.md", 10) }, []fsnotify.Event{ {Name: filepath.FromSlash("content/new1.en.md"), Op: fsnotify.Create}, @@ -513,10 +516,10 @@ func TestMultiSitesRebuild(t *testing.T) { }, { func(t *testing.T) { - p := "content/sect/doc1.en.md" - doc1 := readSource(t, fs, p) + p := "sect/doc1.en.md" + doc1 := readFileFromFs(t, contentFs, p) doc1 += "CHANGED" - writeSource(t, fs, p, doc1) + writeToFs(t, contentFs, p, doc1) }, []fsnotify.Event{{Name: filepath.FromSlash("content/sect/doc1.en.md"), Op: fsnotify.Write}}, func(t *testing.T) { @@ -529,7 +532,7 @@ func TestMultiSitesRebuild(t *testing.T) { // Rename a file { func(t *testing.T) { - if err := fs.Source.Rename("content/new1.en.md", "content/new1renamed.en.md"); err != nil { + if err := contentFs.Rename("new1.en.md", "new1renamed.en.md"); err != nil { t.Fatalf("Rename failed: %s", err) } }, @@ -650,7 +653,7 @@ weight = 15 title = "Svenska" ` - writeNewContentFile(t, fs, "Swedish Contentfile", "2016-01-01", "content/sect/doc1.sv.md", 10) + writeNewContentFile(t, fs.Source, "Swedish Contentfile", "2016-01-01", "content/sect/doc1.sv.md", 10) // replace the config b.WithNewConfig(newConfig) @@ -1038,18 +1041,31 @@ func readFileFromFs(t testing.TB, fs afero.Fs, filename string) string { if err != nil { // Print some debug info root := strings.Split(filename, helpers.FilePathSeparator)[0] - afero.Walk(fs, root, func(path string, info os.FileInfo, err error) error { - if info != nil && !info.IsDir() { - fmt.Println(" ", path) - } - - return nil - }) + printFs(fs, root, os.Stdout) Fatalf(t, "Failed to read file: %s", err) } return string(b) } +func printFs(fs afero.Fs, path string, w io.Writer) { + if fs == nil { + return + } + afero.Walk(fs, path, func(path string, info os.FileInfo, err error) error { + if info != nil && !info.IsDir() { + s := path + if lang, ok := info.(hugofs.LanguageAnnouncer); ok { + s = s + "\tLANG: " + lang.Lang() + } + if fp, ok := info.(hugofs.FilePather); ok { + s = s + "\tRF: " + fp.Filename() + "\tBP: " + fp.BaseDir() + } + fmt.Fprintln(w, " ", s) + } + return nil + }) +} + const testPageTemplate = `--- title: "%s" publishdate: "%s" @@ -1062,9 +1078,9 @@ func newTestPage(title, date string, weight int) string { return fmt.Sprintf(testPageTemplate, title, date, weight, title) } -func writeNewContentFile(t *testing.T, fs *hugofs.Fs, title, date, filename string, weight int) { +func writeNewContentFile(t *testing.T, fs afero.Fs, title, date, filename string, weight int) { content := newTestPage(title, date, weight) - writeSource(t, fs, filename, content) + writeToFs(t, fs, filename, content) } type multiSiteTestBuilder struct { diff --git a/hugolib/language_content_dir_test.go b/hugolib/language_content_dir_test.go new file mode 100644 index 000000000..7195e8e7b --- /dev/null +++ b/hugolib/language_content_dir_test.go @@ -0,0 +1,253 @@ +// Copyright 2018 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hugolib + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +/* + +/en/p1.md +/nn/p1.md + +.Readdir + +- Name() => p1.en.md, p1.nn.md + +.Stat(name) + +.Open() --- real file name + + +*/ + +func TestLanguageContentRoot(t *testing.T) { + t.Parallel() + assert := require.New(t) + + config := ` +baseURL = "https://example.org/" + +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true + +contentDir = "content/main" +workingDir = "/my/project" + +[Languages] +[Languages.en] +weight = 10 +title = "In English" +languageName = "English" + +[Languages.nn] +weight = 20 +title = "På Norsk" +languageName = "Norsk" +# This tells Hugo that all content in this directory is in the Norwegian language. +# It does not have to have the "my-page.nn.md" format. It can, but that is optional. +contentDir = "content/norsk" + +[Languages.sv] +weight = 30 +title = "På Svenska" +languageName = "Svensk" +contentDir = "content/svensk" +` + + pageTemplate := ` +--- +title: %s +slug: %s +weight: %d +--- + +Content. + +` + + pageBundleTemplate := ` +--- +title: %s +weight: %d +--- + +Content. + +` + var contentFiles []string + section := "sect" + + var contentRoot = func(lang string) string { + contentRoot := "content/main" + + switch lang { + case "nn": + contentRoot = "content/norsk" + case "sv": + contentRoot = "content/svensk" + } + return contentRoot + "/" + section + } + + for _, lang := range []string{"en", "nn", "sv"} { + for j := 1; j <= 10; j++ { + if (lang == "nn" || lang == "en") && j%4 == 0 { + // Skip 4 and 8 for nn + // We also skip it for en, but that is added to the Swedish directory below. + continue + } + + if lang == "sv" && j%5 == 0 { + // Skip 5 and 10 for sv + continue + } + + base := fmt.Sprintf("p-%s-%d", lang, j) + slug := fmt.Sprintf("%s", base) + langID := "" + + if lang == "sv" && j%4 == 0 { + // Put an English page in the Swedish content dir. + langID = ".en" + } + + if lang == "en" && j == 8 { + // This should win over the sv variant above. + langID = ".en" + } + + slug += langID + + contentRoot := contentRoot(lang) + + filename := filepath.Join(contentRoot, fmt.Sprintf("page%d%s.md", j, langID)) + contentFiles = append(contentFiles, filename, fmt.Sprintf(pageTemplate, slug, slug, j)) + } + } + + // Put common translations in all of them + for i, lang := range []string{"en", "nn", "sv"} { + contentRoot := contentRoot(lang) + + slug := fmt.Sprintf("common_%s", lang) + + filename := filepath.Join(contentRoot, "common.md") + contentFiles = append(contentFiles, filename, fmt.Sprintf(pageTemplate, slug, slug, 100+i)) + + for j, lang2 := range []string{"en", "nn", "sv"} { + filename := filepath.Join(contentRoot, fmt.Sprintf("translated_all.%s.md", lang2)) + langSlug := slug + "_translated_all_" + lang2 + contentFiles = append(contentFiles, filename, fmt.Sprintf(pageTemplate, langSlug, langSlug, 200+i+j)) + } + + for j, lang2 := range []string{"sv", "nn"} { + if lang == "en" { + continue + } + filename := filepath.Join(contentRoot, fmt.Sprintf("translated_some.%s.md", lang2)) + langSlug := slug + "_translated_some_" + lang2 + contentFiles = append(contentFiles, filename, fmt.Sprintf(pageTemplate, langSlug, langSlug, 300+i+j)) + } + } + + // Add a bundle with some images + for i, lang := range []string{"en", "nn", "sv"} { + contentRoot := contentRoot(lang) + slug := fmt.Sprintf("bundle_%s", lang) + filename := filepath.Join(contentRoot, "mybundle", "index.md") + contentFiles = append(contentFiles, filename, fmt.Sprintf(pageBundleTemplate, slug, 400+i)) + if lang == "en" { + imageFilename := filepath.Join(contentRoot, "mybundle", "logo.png") + contentFiles = append(contentFiles, imageFilename, "PNG Data") + } + imageFilename := filepath.Join(contentRoot, "mybundle", "featured.png") + contentFiles = append(contentFiles, imageFilename, fmt.Sprintf("PNG Data for %s", lang)) + + // Add some bundled pages + contentFiles = append(contentFiles, filepath.Join(contentRoot, "mybundle", "p1.md"), fmt.Sprintf(pageBundleTemplate, slug, 401+i)) + contentFiles = append(contentFiles, filepath.Join(contentRoot, "mybundle", "sub", "p1.md"), fmt.Sprintf(pageBundleTemplate, slug, 402+i)) + + } + + b := newTestSitesBuilder(t) + b.WithWorkingDir("/my/project").WithConfigFile("toml", config).WithContent(contentFiles...).CreateSites() + + _ = os.Stdout + //printFs(b.H.BaseFs.ContentFs, "/", os.Stdout) + + b.Build(BuildCfg{}) + + assert.Equal(3, len(b.H.Sites)) + + enSite := b.H.Sites[0] + nnSite := b.H.Sites[1] + svSite := b.H.Sites[2] + + //dumpPages(nnSite.RegularPages...) + assert.Equal(12, len(nnSite.RegularPages)) + assert.Equal(13, len(enSite.RegularPages)) + + assert.Equal(10, len(svSite.RegularPages)) + + for i, p := range enSite.RegularPages { + j := i + 1 + msg := fmt.Sprintf("Test %d", j) + assert.Equal("en", p.Lang(), msg) + assert.Equal("sect", p.Section()) + if j < 9 { + if j%4 == 0 { + assert.Contains(p.Title(), fmt.Sprintf("p-sv-%d.en", i+1), msg) + } else { + assert.Contains(p.Title(), "p-en", msg) + } + } + } + + // Check bundles + bundleEn := enSite.RegularPages[len(enSite.RegularPages)-1] + bundleNn := nnSite.RegularPages[len(nnSite.RegularPages)-1] + bundleSv := svSite.RegularPages[len(svSite.RegularPages)-1] + + assert.Equal("/en/sect/mybundle/", bundleEn.RelPermalink()) + assert.Equal("/sv/sect/mybundle/", bundleSv.RelPermalink()) + + assert.Equal(4, len(bundleEn.Resources)) + assert.Equal(4, len(bundleNn.Resources)) + assert.Equal(4, len(bundleSv.Resources)) + + assert.Equal("/en/sect/mybundle/logo.png", bundleEn.Resources.GetMatch("logo*").RelPermalink()) + assert.Equal("/nn/sect/mybundle/logo.png", bundleNn.Resources.GetMatch("logo*").RelPermalink()) + assert.Equal("/sv/sect/mybundle/logo.png", bundleSv.Resources.GetMatch("logo*").RelPermalink()) + + b.AssertFileContent("/my/project/public/sv/sect/mybundle/featured.png", "PNG Data for sv") + b.AssertFileContent("/my/project/public/nn/sect/mybundle/featured.png", "PNG Data for nn") + b.AssertFileContent("/my/project/public/en/sect/mybundle/featured.png", "PNG Data for en") + b.AssertFileContent("/my/project/public/en/sect/mybundle/logo.png", "PNG Data") + b.AssertFileContent("/my/project/public/sv/sect/mybundle/logo.png", "PNG Data") + b.AssertFileContent("/my/project/public/nn/sect/mybundle/logo.png", "PNG Data") + |