Create robots.txt in the domain root directory

Before a robots.txt is created in every Site. So in public/robots.txt if there are no languages (was correct). But if there are multiple languages in every language directory, too (was wrong). If defaultContentLanguageInSubdir is true, no language is created into the root directory, so no robots.txt is in the root directory (was wrong). If multihosts are configured for each language, that is the only case where one robots.txt must be created in each language directory (was correct).

I've changed the behaviour, that only in the multihost case the robots.txt is created in the language directories. In any other case it is created in public/robots.txt. I've also added tests that files are not created in the wrong directories.

Fixes #5160
See also #4193
This commit is contained in:
Nico 2020-06-20 15:00:25 +02:00 committed by Bjørn Erik Pedersen
parent 6ff435aa3f
commit 3466884e36
6 changed files with 59 additions and 6 deletions

View file

@ -49,6 +49,7 @@ import (
"github.com/gohugoio/hugo/langs/i18n" "github.com/gohugoio/hugo/langs/i18n"
"github.com/gohugoio/hugo/resources/page" "github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/resources/page/pagemeta"
"github.com/gohugoio/hugo/tpl" "github.com/gohugoio/hugo/tpl"
"github.com/gohugoio/hugo/tpl/tplimpl" "github.com/gohugoio/hugo/tpl/tplimpl"
) )
@ -690,7 +691,7 @@ func (cfg *BuildCfg) shouldRender(p *pageState) bool {
return false return false
} }
func (h *HugoSites) renderCrossSitesArtifacts() error { func (h *HugoSites) renderCrossSitesSitemap() error {
if !h.multilingual.enabled() || h.IsMultihost() { if !h.multilingual.enabled() || h.IsMultihost() {
return nil return nil
@ -716,6 +717,38 @@ func (h *HugoSites) renderCrossSitesArtifacts() error {
s.siteCfg.sitemap.Filename, h.toSiteInfos(), templ) s.siteCfg.sitemap.Filename, h.toSiteInfos(), templ)
} }
func (h *HugoSites) renderCrossSitesRobotsTXT() error {
if h.multihost {
return nil
}
if !h.Cfg.GetBool("enableRobotsTXT") {
return nil
}
s := h.Sites[0]
p, err := newPageStandalone(&pageMeta{
s: s,
kind: kindRobotsTXT,
urlPaths: pagemeta.URLPath{
URL: "robots.txt",
},
},
output.RobotsTxtFormat)
if err != nil {
return err
}
if !p.render {
return nil
}
templ := s.lookupLayouts("robots.txt", "_default/robots.txt", "_internal/_default/robots.txt")
return s.renderAndWritePage(&s.PathSpec.ProcessingStats.Pages, "Robots Txt", "robots.txt", p, templ)
}
func (h *HugoSites) removePageByFilename(filename string) { func (h *HugoSites) removePageByFilename(filename string) {
h.getContentMaps().withMaps(func(m *pageMap) error { h.getContentMaps().withMaps(func(m *pageMap) error {
m.deleteBundleMatching(func(b *contentNode) bool { m.deleteBundleMatching(func(b *contentNode) bool {

View file

@ -334,7 +334,10 @@ func (h *HugoSites) render(config *BuildCfg) error {
} }
if !config.SkipRender { if !config.SkipRender {
if err := h.renderCrossSitesArtifacts(); err != nil { if err := h.renderCrossSitesSitemap(); err != nil {
return err
}
if err := h.renderCrossSitesRobotsTXT(); err != nil {
return err return err
} }
} }

View file

@ -255,8 +255,10 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
b.AssertFileContent("public/fr/404.html", "404|fr|404 Page not found") b.AssertFileContent("public/fr/404.html", "404|fr|404 Page not found")
// Check robots.txt // Check robots.txt
b.AssertFileContent("public/en/robots.txt", "robots|en|") // the domain root is the public directory, so the robots.txt has to be created there and not in the language directories
b.AssertFileContent("public/nn/robots.txt", "robots|nn|") b.AssertFileContent("public/robots.txt", "robots")
b.AssertFileDoesNotExist("public/en/robots.txt")
b.AssertFileDoesNotExist("public/nn/robots.txt")
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Permalink: http://example.com/blog/en/sect/doc1-slug/") b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Permalink: http://example.com/blog/en/sect/doc1-slug/")
b.AssertFileContent("public/en/sect/doc2/index.html", "Permalink: http://example.com/blog/en/sect/doc2/") b.AssertFileContent("public/en/sect/doc2/index.html", "Permalink: http://example.com/blog/en/sect/doc2/")

View file

@ -19,6 +19,7 @@ disablePathToLower = true
defaultContentLanguage = "fr" defaultContentLanguage = "fr"
defaultContentLanguageInSubdir = false defaultContentLanguageInSubdir = false
staticDir = ["s1", "s2"] staticDir = ["s1", "s2"]
enableRobotsTXT = true
[permalinks] [permalinks]
other = "/somewhere/else/:filename" other = "/somewhere/else/:filename"
@ -73,6 +74,12 @@ languageName = "Nynorsk"
c.Assert(pageWithURLInFrontMatter.RelPermalink(), qt.Equals, "/docs/superbob/") c.Assert(pageWithURLInFrontMatter.RelPermalink(), qt.Equals, "/docs/superbob/")
b.AssertFileContent("public/en/superbob/index.html", "doc3|Hello|en") b.AssertFileContent("public/en/superbob/index.html", "doc3|Hello|en")
// the domain root is the language directory for each language, so the robots.txt is created in the language directories
b.AssertFileContent("public/en/robots.txt", "robots|en")
b.AssertFileContent("public/fr/robots.txt", "robots|fr")
b.AssertFileContent("public/nn/robots.txt", "robots|nn")
b.AssertFileDoesNotExist("public/robots.txt")
// check alias: // check alias:
b.AssertFileContent("public/en/al/alias1/index.html", `content="0; url=https://example.com/docs/superbob/"`) b.AssertFileContent("public/en/al/alias1/index.html", `content="0; url=https://example.com/docs/superbob/"`)
b.AssertFileContent("public/en/al/alias2/index.html", `content="0; url=https://example.com/docs/superbob/"`) b.AssertFileContent("public/en/al/alias2/index.html", `content="0; url=https://example.com/docs/superbob/"`)

View file

@ -1209,9 +1209,11 @@ func (s *Site) render(ctx *siteRenderContext) (err error) {
return return
} }
if ctx.multihost {
if err = s.renderRobotsTXT(); err != nil { if err = s.renderRobotsTXT(); err != nil {
return return
} }
}
if err = s.render404(); err != nil { if err = s.render404(); err != nil {
return return

View file

@ -726,6 +726,12 @@ func (s *sitesBuilder) AssertFileContent(filename string, matches ...string) {
} }
} }
func (s *sitesBuilder) AssertFileDoesNotExist(filename string) {
if s.CheckExists(filename) {
s.Fatalf("File %q exists but must not exist.", filename)
}
}
func (s *sitesBuilder) AssertImage(width, height int, filename string) { func (s *sitesBuilder) AssertImage(width, height int, filename string) {
filename = filepath.Join(s.workingDir, filename) filename = filepath.Join(s.workingDir, filename)
f, err := s.Fs.Destination.Open(filename) f, err := s.Fs.Destination.Open(filename)