hugolib: Make sure everything ends up in its lang root in multihost mode - hugo - [fork] hugo port for 9front
 (HTM) git clone git@git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 089fe49309cd9cadba3ae9a5eddfd69622941a70
 (DIR) parent 118b83d74b5caaae6646ec031d59b8ab3491c6b2
 (HTM) Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
       Date:   Mon, 20 Nov 2017 10:34:30 +0100
       
       hugolib: Make sure everything ends up in its lang root in multihost mode
       
       Fixes #4105
       
       Diffstat:
         M hugolib/hugo_sites_build_test.go    |       2 +-
         M hugolib/hugo_sites_multihost_test.… |      16 ++++++++++++++++
         M hugolib/page_paths.go               |      22 +++++++++++++++-------
         M hugolib/page_paths_test.go          |     277 ++++++++++++++++---------------
         M hugolib/site_render.go              |       8 ++++++++
       
       5 files changed, 181 insertions(+), 144 deletions(-)
       ---
 (DIR) diff --git a/hugolib/hugo_sites_build_test.go b/hugolib/hugo_sites_build_test.go
       @@ -254,7 +254,6 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
        
                doc3 := enSite.RegularPages[2]
                permalink = doc3.Permalink()
       -        require.NoError(t, err, "permalink call failed")
                // Note that /superbob is a custom URL set in frontmatter.
                // We respect that URL literally (it can be /search.json)
                // and do no not do any language code prefixing.
       @@ -1155,6 +1154,7 @@ NOTE: without slug, "doc2" should be used, without ".en" as URL
        title: doc3
        weight: 3
        publishdate: "2000-01-03"
       +aliases: [/en/al/alias1,/al/alias2/]
        tags:
         - tag2
         - tag1
 (DIR) diff --git a/hugolib/hugo_sites_multihost_test.go b/hugolib/hugo_sites_multihost_test.go
       @@ -68,6 +68,22 @@ languageName = "Nynorsk"
                assert.Len(s1h.Translations(), 2)
                assert.Equal("https://example.com/", s1h.Permalink())
        
       +        // For “regular multilingual” we kept the aliases pages with url in front matter
       +        // as a literal value that we use as is.
       +        // There is an ambiguity in the guessing.
       +        // For multihost, we never want any content in the root.
       +        //
       +        // check url in front matter:
       +        pageWithURLInFrontMatter := s1.getPage(KindPage, "sect/doc3.en.md")
       +        assert.NotNil(pageWithURLInFrontMatter)
       +        assert.Equal("/superbob", pageWithURLInFrontMatter.URL())
       +        assert.Equal("/superbob/", pageWithURLInFrontMatter.RelPermalink())
       +        th.assertFileContent("public/en/superbob/index.html", "doc3|Hello|en")
       +
       +        // check alias:
       +        th.assertFileContent("public/en/al/alias1/index.html", `content="0; url=https://example.com/superbob/"`)
       +        th.assertFileContent("public/en/al/alias2/index.html", `content="0; url=https://example.com/superbob/"`)
       +
                s2 := sites.Sites[1]
                assert.Equal([]string{"s1", "s2", "frs1", "frs2"}, s2.StaticDirs())
        
 (DIR) diff --git a/hugolib/page_paths.go b/hugolib/page_paths.go
       @@ -53,6 +53,9 @@ type targetPathDescriptor struct {
                // language subdir.
                LangPrefix string
        
       +        // Whether this is a multihost multilingual setup.
       +        IsMultihost bool
       +
                // Page.URLPath.URL. Will override any Slug etc. for regular pages.
                URL string
        
       @@ -81,12 +84,13 @@ func (p *Page) createTargetPathDescriptor(t output.Format) (targetPathDescriptor
        func (p *Page) initTargetPathDescriptor() error {
        
                d := &targetPathDescriptor{
       -                PathSpec: p.s.PathSpec,
       -                Kind:     p.Kind,
       -                Sections: p.sections,
       -                UglyURLs: p.s.Info.uglyURLs,
       -                Dir:      filepath.ToSlash(p.Source.Dir()),
       -                URL:      p.URLPath.URL,
       +                PathSpec:    p.s.PathSpec,
       +                Kind:        p.Kind,
       +                Sections:    p.sections,
       +                UglyURLs:    p.s.Info.uglyURLs,
       +                Dir:         filepath.ToSlash(p.Source.Dir()),
       +                URL:         p.URLPath.URL,
       +                IsMultihost: p.s.owner.IsMultihost(),
                }
        
                if p.Slug != "" {
       @@ -177,7 +181,11 @@ func createTargetPath(d targetPathDescriptor) string {
                if d.Kind == KindPage {
                        // Always use URL if it's specified
                        if d.URL != "" {
       -                        pagePath = filepath.Join(pagePath, d.URL)
       +                        if d.IsMultihost && d.LangPrefix != "" && !strings.HasPrefix(d.URL, "/"+d.LangPrefix) {
       +                                pagePath = filepath.Join(d.LangPrefix, pagePath, d.URL)
       +                        } else {
       +                                pagePath = filepath.Join(pagePath, d.URL)
       +                        }
                                if strings.HasSuffix(d.URL, "/") || !strings.Contains(d.URL, ".") {
                                        pagePath = filepath.Join(pagePath, d.Type.BaseName+d.Type.MediaType.FullSuffix())
                                }
 (DIR) diff --git a/hugolib/page_paths_test.go b/hugolib/page_paths_test.go
       @@ -40,151 +40,156 @@ func TestPageTargetPath(t *testing.T) {
                        BaseName:  "_redirects",
                }
        
       -        for _, langPrefix := range []string{"", "no"} {
       -                for _, uglyURLs := range []bool{false, true} {
       -                        t.Run(fmt.Sprintf("langPrefix=%q,uglyURLs=%t", langPrefix, uglyURLs),
       -                                func(t *testing.T) {
       -
       -                                        tests := []struct {
       -                                                name     string
       -                                                d        targetPathDescriptor
       -                                                expected string
       -                                        }{
       -                                                {"JSON home", targetPathDescriptor{Kind: KindHome, Type: output.JSONFormat}, "/index.json"},
       -                                                {"AMP home", targetPathDescriptor{Kind: KindHome, Type: output.AMPFormat}, "/amp/index.html"},
       -                                                {"HTML home", targetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: output.HTMLFormat}, "/index.html"},
       -                                                {"Netlify redirects", targetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: noExtDelimFormat}, "/_redirects"},
       -                                                {"HTML section list", targetPathDescriptor{
       -                                                        Kind:     KindSection,
       -                                                        Sections: []string{"sect1"},
       -                                                        BaseName: "_index",
       -                                                        Type:     output.HTMLFormat}, "/sect1/index.html"},
       -                                                {"HTML taxonomy list", targetPathDescriptor{
       -                                                        Kind:     KindTaxonomy,
       -                                                        Sections: []string{"tags", "hugo"},
       -                                                        BaseName: "_index",
       -                                                        Type:     output.HTMLFormat}, "/tags/hugo/index.html"},
       -                                                {"HTML taxonomy term", targetPathDescriptor{
       -                                                        Kind:     KindTaxonomy,
       -                                                        Sections: []string{"tags"},
       -                                                        BaseName: "_index",
       -                                                        Type:     output.HTMLFormat}, "/tags/index.html"},
       -                                                {
       -                                                        "HTML page", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/a/b",
       -                                                                BaseName: "mypage",
       -                                                                Sections: []string{"a"},
       -                                                                Type:     output.HTMLFormat}, "/a/b/mypage/index.html"},
       -
       -                                                {
       -                                                        // Issue #3396
       -                                                        "HTML page with index as base", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/a/b",
       -                                                                BaseName: "index",
       -                                                                Sections: []string{"a"},
       -                                                                Type:     output.HTMLFormat}, "/a/b/index.html"},
       -
       -                                                {
       -                                                        "HTML page with special chars", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/a/b",
       -                                                                BaseName: "My Page!",
       -                                                                Type:     output.HTMLFormat}, "/a/b/My-Page/index.html"},
       -                                                {"RSS home", targetPathDescriptor{Kind: kindRSS, Type: output.RSSFormat}, "/index.xml"},
       -                                                {"RSS section list", targetPathDescriptor{
       -                                                        Kind:     kindRSS,
       -                                                        Sections: []string{"sect1"},
       -                                                        Type:     output.RSSFormat}, "/sect1/index.xml"},
       -                                                {
       -                                                        "AMP page", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/a/b/c",
       -                                                                BaseName: "myamp",
       -                                                                Type:     output.AMPFormat}, "/amp/a/b/c/myamp/index.html"},
       -                                                {
       -                                                        "AMP page with URL with suffix", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/sect/",
       -                                                                BaseName: "mypage",
       -                                                                URL:      "/some/other/url.xhtml",
       -                                                                Type:     output.HTMLFormat}, "/some/other/url.xhtml"},
       -                                                {
       -                                                        "JSON page with URL without suffix", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/sect/",
       -                                                                BaseName: "mypage",
       -                                                                URL:      "/some/other/path/",
       -                                                                Type:     output.JSONFormat}, "/some/other/path/index.json"},
       -                                                {
       -                                                        "JSON page with URL without suffix and no trailing slash", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/sect/",
       -                                                                BaseName: "mypage",
       -                                                                URL:      "/some/other/path",
       -                                                                Type:     output.JSONFormat}, "/some/other/path/index.json"},
       -                                                {
       -                                                        "HTML page with expanded permalink", targetPathDescriptor{
       -                                                                Kind:              KindPage,
       -                                                                Dir:               "/a/b",
       -                                                                BaseName:          "mypage",
       -                                                                ExpandedPermalink: "/2017/10/my-title",
       -                                                                Type:              output.HTMLFormat}, "/2017/10/my-title/index.html"},
       -                                                {
       -                                                        "Paginated HTML home", targetPathDescriptor{
       -                                                                Kind:     KindHome,
       +        for _, multiHost := range []bool{false, true} {
       +                for _, langPrefix := range []string{"", "no"} {
       +                        for _, uglyURLs := range []bool{false, true} {
       +                                t.Run(fmt.Sprintf("multihost=%t,langPrefix=%q,uglyURLs=%t", multiHost, langPrefix, uglyURLs),
       +                                        func(t *testing.T) {
       +
       +                                                tests := []struct {
       +                                                        name     string
       +                                                        d        targetPathDescriptor
       +                                                        expected string
       +                                                }{
       +                                                        {"JSON home", targetPathDescriptor{Kind: KindHome, Type: output.JSONFormat}, "/index.json"},
       +                                                        {"AMP home", targetPathDescriptor{Kind: KindHome, Type: output.AMPFormat}, "/amp/index.html"},
       +                                                        {"HTML home", targetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: output.HTMLFormat}, "/index.html"},
       +                                                        {"Netlify redirects", targetPathDescriptor{Kind: KindHome, BaseName: "_index", Type: noExtDelimFormat}, "/_redirects"},
       +                                                        {"HTML section list", targetPathDescriptor{
       +                                                                Kind:     KindSection,
       +                                                                Sections: []string{"sect1"},
                                                                        BaseName: "_index",
       -                                                                Type:     output.HTMLFormat,
       -                                                                Addends:  "page/3"}, "/page/3/index.html"},
       -                                                {
       -                                                        "Paginated Taxonomy list", targetPathDescriptor{
       +                                                                Type:     output.HTMLFormat}, "/sect1/index.html"},
       +                                                        {"HTML taxonomy list", targetPathDescriptor{
                                                                        Kind:     KindTaxonomy,
       -                                                                BaseName: "_index",
                                                                        Sections: []string{"tags", "hugo"},
       -                                                                Type:     output.HTMLFormat,
       -                                                                Addends:  "page/3"}, "/tags/hugo/page/3/index.html"},
       -                                                {
       -                                                        "Regular page with addend", targetPathDescriptor{
       -                                                                Kind:     KindPage,
       -                                                                Dir:      "/a/b",
       -                                                                BaseName: "mypage",
       -                                                                Addends:  "c/d/e",
       -                                                                Type:     output.HTMLFormat}, "/a/b/mypage/c/d/e/index.html"},
       -                                        }
       -
       -                                        for i, test := range tests {
       -                                                test.d.PathSpec = pathSpec
       -                                                test.d.UglyURLs = uglyURLs
       -                                                test.d.LangPrefix = langPrefix
       -                                                test.d.Dir = filepath.FromSlash(test.d.Dir)
       -                                                isUgly := uglyURLs && !test.d.Type.NoUgly
       -
       -                                                expected := test.expected
       -
       -                                                // TODO(bep) simplify
       -                                                if test.d.Kind == KindPage && test.d.BaseName == test.d.Type.BaseName {
       -
       -                                                } else if test.d.Kind == KindHome && test.d.Type.Path != "" {
       -                                                } else if (!strings.HasPrefix(expected, "/index") || test.d.Addends != "") && test.d.URL == "" && isUgly {
       -                                                        expected = strings.Replace(expected,
       -                                                                "/"+test.d.Type.BaseName+"."+test.d.Type.MediaType.Suffix,
       -                                                                "."+test.d.Type.MediaType.Suffix, -1)
       +                                                                BaseName: "_index",
       +                                                                Type:     output.HTMLFormat}, "/tags/hugo/index.html"},
       +                                                        {"HTML taxonomy term", targetPathDescriptor{
       +                                                                Kind:     KindTaxonomy,
       +                                                                Sections: []string{"tags"},
       +                                                                BaseName: "_index",
       +                                                                Type:     output.HTMLFormat}, "/tags/index.html"},
       +                                                        {
       +                                                                "HTML page", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/a/b",
       +                                                                        BaseName: "mypage",
       +                                                                        Sections: []string{"a"},
       +                                                                        Type:     output.HTMLFormat}, "/a/b/mypage/index.html"},
       +
       +                                                        {
       +                                                                // Issue #3396
       +                                                                "HTML page with index as base", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/a/b",
       +                                                                        BaseName: "index",
       +                                                                        Sections: []string{"a"},
       +                                                                        Type:     output.HTMLFormat}, "/a/b/index.html"},
       +
       +                                                        {
       +                                                                "HTML page with special chars", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/a/b",
       +                                                                        BaseName: "My Page!",
       +                                                                        Type:     output.HTMLFormat}, "/a/b/My-Page/index.html"},
       +                                                        {"RSS home", targetPathDescriptor{Kind: kindRSS, Type: output.RSSFormat}, "/index.xml"},
       +                                                        {"RSS section list", targetPathDescriptor{
       +                                                                Kind:     kindRSS,
       +                                                                Sections: []string{"sect1"},
       +                                                                Type:     output.RSSFormat}, "/sect1/index.xml"},
       +                                                        {
       +                                                                "AMP page", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/a/b/c",
       +                                                                        BaseName: "myamp",
       +                                                                        Type:     output.AMPFormat}, "/amp/a/b/c/myamp/index.html"},
       +                                                        {
       +                                                                "AMP page with URL with suffix", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/sect/",
       +                                                                        BaseName: "mypage",
       +                                                                        URL:      "/some/other/url.xhtml",
       +                                                                        Type:     output.HTMLFormat}, "/some/other/url.xhtml"},
       +                                                        {
       +                                                                "JSON page with URL without suffix", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/sect/",
       +                                                                        BaseName: "mypage",
       +                                                                        URL:      "/some/other/path/",
       +                                                                        Type:     output.JSONFormat}, "/some/other/path/index.json"},
       +                                                        {
       +                                                                "JSON page with URL without suffix and no trailing slash", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/sect/",
       +                                                                        BaseName: "mypage",
       +                                                                        URL:      "/some/other/path",
       +                                                                        Type:     output.JSONFormat}, "/some/other/path/index.json"},
       +                                                        {
       +                                                                "HTML page with expanded permalink", targetPathDescriptor{
       +                                                                        Kind:              KindPage,
       +                                                                        Dir:               "/a/b",
       +                                                                        BaseName:          "mypage",
       +                                                                        ExpandedPermalink: "/2017/10/my-title",
       +                                                                        Type:              output.HTMLFormat}, "/2017/10/my-title/index.html"},
       +                                                        {
       +                                                                "Paginated HTML home", targetPathDescriptor{
       +                                                                        Kind:     KindHome,
       +                                                                        BaseName: "_index",
       +                                                                        Type:     output.HTMLFormat,
       +                                                                        Addends:  "page/3"}, "/page/3/index.html"},
       +                                                        {
       +                                                                "Paginated Taxonomy list", targetPathDescriptor{
       +                                                                        Kind:     KindTaxonomy,
       +                                                                        BaseName: "_index",
       +                                                                        Sections: []string{"tags", "hugo"},
       +                                                                        Type:     output.HTMLFormat,
       +                                                                        Addends:  "page/3"}, "/tags/hugo/page/3/index.html"},
       +                                                        {
       +                                                                "Regular page with addend", targetPathDescriptor{
       +                                                                        Kind:     KindPage,
       +                                                                        Dir:      "/a/b",
       +                                                                        BaseName: "mypage",
       +                                                                        Addends:  "c/d/e",
       +                                                                        Type:     output.HTMLFormat}, "/a/b/mypage/c/d/e/index.html"},
                                                        }
        
       -                                                if test.d.LangPrefix != "" && !(test.d.Kind == KindPage && test.d.URL != "") {
       -                                                        expected = "/" + test.d.LangPrefix + expected
       -                                                }
       +                                                for i, test := range tests {
       +                                                        test.d.PathSpec = pathSpec
       +                                                        test.d.UglyURLs = uglyURLs
       +                                                        test.d.LangPrefix = langPrefix
       +                                                        test.d.IsMultihost = multiHost
       +                                                        test.d.Dir = filepath.FromSlash(test.d.Dir)
       +                                                        isUgly := uglyURLs && !test.d.Type.NoUgly
       +
       +                                                        expected := test.expected
       +
       +                                                        // TODO(bep) simplify
       +                                                        if test.d.Kind == KindPage && test.d.BaseName == test.d.Type.BaseName {
       +
       +                                                        } else if test.d.Kind == KindHome && test.d.Type.Path != "" {
       +                                                        } else if (!strings.HasPrefix(expected, "/index") || test.d.Addends != "") && test.d.URL == "" && isUgly {
       +                                                                expected = strings.Replace(expected,
       +                                                                        "/"+test.d.Type.BaseName+"."+test.d.Type.MediaType.Suffix,
       +                                                                        "."+test.d.Type.MediaType.Suffix, -1)
       +                                                        }
       +
       +                                                        if test.d.LangPrefix != "" && !(test.d.Kind == KindPage && test.d.URL != "") {
       +                                                                expected = "/" + test.d.LangPrefix + expected
       +                                                        } else if multiHost && test.d.LangPrefix != "" && test.d.URL != "" {
       +                                                                expected = "/" + test.d.LangPrefix + expected
       +                                                        }
        
       -                                                expected = filepath.FromSlash(expected)
       +                                                        expected = filepath.FromSlash(expected)
        
       -                                                pagePath := createTargetPath(test.d)
       +                                                        pagePath := createTargetPath(test.d)
        
       -                                                if pagePath != expected {
       -                                                        t.Fatalf("[%d] [%s] targetPath expected %q, got: %q", i, test.name, expected, pagePath)
       +                                                        if pagePath != expected {
       +                                                                t.Fatalf("[%d] [%s] targetPath expected %q, got: %q", i, test.name, expected, pagePath)
       +                                                        }
                                                        }
       -                                        }
       -                                })
       +                                        })
       +                        }
                        }
                }
        }
 (DIR) diff --git a/hugolib/site_render.go b/hugolib/site_render.go
       @@ -16,6 +16,7 @@ package hugolib
        import (
                "fmt"
                "path"
       +        "strings"
                "sync"
        
                "github.com/gohugoio/hugo/helpers"
       @@ -380,6 +381,13 @@ func (s *Site) renderAliases() error {
                                                a = path.Join(a, f.Path)
                                        }
        
       +                                lang := p.Lang()
       +
       +                                if s.owner.multihost && !strings.HasPrefix(a, "/"+lang) {
       +                                        // These need to be in its language root.
       +                                        a = path.Join(lang, a)
       +                                }
       +
                                        if err := s.writeDestAlias(a, plink, p); err != nil {
                                                return err
                                        }