Add sitemap index for multilingual sites
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 4 Aug 2016 20:12:19 +0000 (22:12 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 6 Sep 2016 15:32:17 +0000 (18:32 +0300)
See #2309

hugolib/hugo_sites.go
hugolib/hugo_sites_test.go
hugolib/public/404.html [deleted file]
hugolib/public/index.html [deleted file]
hugolib/public/rss [deleted file]
hugolib/public/sitemap.xml [deleted file]
hugolib/site.go
tpl/template_embedded.go

index 76f9979fd90b470740c5b3665195dfcdd32b28ce..8356030485ec98373f843fbc4b890b7ef1589cb1 100644 (file)
@@ -61,6 +61,14 @@ func (h HugoSites) Reset() {
        }
 }
 
+func (h HugoSites) siteInfos() []*SiteInfo {
+       infos := make([]*SiteInfo, len(h.Sites))
+       for i, s := range h.Sites {
+               infos[i] = &s.Info
+       }
+       return infos
+}
+
 type BuildCfg struct {
        // Whether we are in watch (server) mode
        Watching bool
@@ -118,9 +126,9 @@ func (h HugoSites) Build(config BuildCfg) error {
                return err
        }
 
-       for _, s := range h.Sites {
+       if !config.skipRender {
+               for _, s := range h.Sites {
 
-               if !config.skipRender {
                        if err := s.Render(); err != nil {
                                return err
                        }
@@ -129,7 +137,10 @@ func (h HugoSites) Build(config BuildCfg) error {
                                s.Stats()
                        }
                }
-               // TODO(bep) ml lang in site.Info?
+
+               if err := h.render(); err != nil {
+                       return err
+               }
        }
 
        if config.PrintStats {
@@ -180,6 +191,10 @@ func (h HugoSites) Rebuild(config BuildCfg, events ...fsnotify.Event) error {
                                s.Stats()
                        }
                }
+
+               if err := h.render(); err != nil {
+                       return err
+               }
        }
 
        if config.PrintStats {
@@ -190,6 +205,28 @@ func (h HugoSites) Rebuild(config BuildCfg, events ...fsnotify.Event) error {
 
 }
 
+// Render the cross-site artifacts.
+func (h *HugoSites) render() error {
+
+       if !h.Multilingual.enabled() {
+               return nil
+       }
+
+       // TODO(bep) DRY
+       sitemapDefault := parseSitemap(viper.GetStringMap("Sitemap"))
+
+       s := h.Sites[0]
+
+       smLayouts := []string{"sitemapindex.xml", "_default/sitemapindex.xml", "_internal/_default/sitemapindex.xml"}
+
+       if err := s.renderAndWriteXML("sitemapindex", sitemapDefault.Filename,
+               h.siteInfos(), s.appendThemeTemplates(smLayouts)...); err != nil {
+               return err
+       }
+
+       return nil
+}
+
 func (s *HugoSites) setupTranslations(master *Site) {
 
        for _, p := range master.rawAllPages {
index cbd6bd627c38bbade2de66baa577783611744a62..185c241a51a5583183c3f77dc07515f40a8a34e2 100644 (file)
@@ -126,11 +126,18 @@ func TestMultiSites(t *testing.T) {
                assert.Equal(t, "fr", frenchPage.Lang())
        }
 
+       // Check redirect to main language, French
        languageRedirect := readDestination(t, "public/index.html")
-
-       // French is the main content language
        require.True(t, strings.Contains(languageRedirect, "0; url=http://example.com/blog/fr"), languageRedirect)
 
+       // Check sitemap(s)
+       sitemapIndex := readDestination(t, "public/sitemap.xml")
+       require.True(t, strings.Contains(sitemapIndex, "<loc>http:/example.com/blog/en/sitemap.xml</loc>"), sitemapIndex)
+       require.True(t, strings.Contains(sitemapIndex, "<loc>http:/example.com/blog/fr/sitemap.xml</loc>"), sitemapIndex)
+       sitemapEn := readDestination(t, "public/en/sitemap.xml")
+       sitemapFr := readDestination(t, "public/fr/sitemap.xml")
+       require.True(t, strings.Contains(sitemapEn, "http://example.com/blog/en/sect/doc2/"), sitemapEn)
+       require.True(t, strings.Contains(sitemapFr, "http://example.com/blog/fr/sect/doc1/"), sitemapFr)
 }
 
 func TestMultiSitesRebuild(t *testing.T) {
diff --git a/hugolib/public/404.html b/hugolib/public/404.html
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/hugolib/public/index.html b/hugolib/public/index.html
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/hugolib/public/rss b/hugolib/public/rss
deleted file mode 100644 (file)
index bbf7390..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
-  <channel>
-    <title></title>
-    <link>/rss/</link>
-    <description>Recent content on </description>
-    <generator>Hugo -- gohugo.io</generator>
-    <atom:link href="/rss/" rel="self" type="application/rss+xml" />
-    
-  </channel>
-</rss>
\ No newline at end of file
diff --git a/hugolib/public/sitemap.xml b/hugolib/public/sitemap.xml
deleted file mode 100644 (file)
index f02c32c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
-  
-  <url>
-    <loc>/</loc>
-  </url>
-  
-</urlset>
\ No newline at end of file
index 776876980f1a58a6b6871e39ae9cfc9e950737e9..06d7ed0743c114d07e7e8b86c25f03a040f9c6b9 100644 (file)
@@ -170,10 +170,10 @@ type SiteInfo struct {
        paginationPageCount   uint64
        Data                  *map[string]interface{}
 
-       Multilingual    bool
-       CurrentLanguage string
-       LanguagePrefix  string
-       Languages       Languages
+       Multilingual   bool
+       Language       *Language
+       LanguagePrefix string
+       Languages      Languages
 }
 
 // SiteSocial is a place to put social details on a site level. These are the
@@ -831,6 +831,21 @@ func (s *Site) initialize() (err error) {
        return
 }
 
+// HomeURL is a convenience method giving the absolute URL to the home page.
+func (s *SiteInfo) HomeAbsURL() string {
+       base := "/"
+       if s.Multilingual {
+               base = s.Language.Lang
+       }
+       return helpers.AbsURL(base)
+}
+
+// SitemapAbsURL is a convenience method giving the absolute URL to the sitemap.
+func (s *SiteInfo) SitemapAbsURL() string {
+       sitemapDefault := parseSitemap(viper.GetStringMap("Sitemap"))
+       return path.Join(s.HomeAbsURL(), sitemapDefault.Filename)
+}
+
 func (s *Site) initializeSiteInfo() {
 
        var (
@@ -864,7 +879,7 @@ func (s *Site) initializeSiteInfo() {
                DisqusShortname: lang.GetString("DisqusShortname"),
                // TODO(bep) multilang, consolidate the below (make into methods etc.)
                Multilingual:          s.multilingualEnabled(),
-               CurrentLanguage:       lang.Lang,
+               Language:              lang,
                LanguagePrefix:        languagePrefix,
                Languages:             languages,
                GoogleAnalytics:       lang.GetString("GoogleAnalytics"),
index dae36a297a8ecca6479c793ab1dec9396d927f0f..c13768dda9b8d943b9cc60c7eb0688678feadbe0 100644 (file)
@@ -100,6 +100,19 @@ func (t *GoHTMLTemplate) EmbedTemplates() {
   {{ end }}
 </urlset>`)
 
+       // For multilanguage sites
+       t.AddInternalTemplate("_default", "sitemapindex.xml", `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+       {{ range . }}
+       <sitemap>
+               <loc>{{ .SitemapAbsURL }}</loc>
+               {{ if not .LastChange.IsZero }}
+               <lastmod>{{ .LastChange.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</lastmod>
+               {{ end }}
+       </sitemap>
+       {{ end }}
+</sitemapindex>
+`)
+
        t.AddInternalTemplate("", "pagination.html", `{{ $pag := $.Paginator }}
     {{ if gt $pag.TotalPages 1 }}
     <ul class="pagination">