hugo/hugolib/hugo_sites_build_test.go

1408 lines
39 KiB
Go
Raw Normal View History

package hugolib
import (
"fmt"
"path/filepath"
"strings"
"testing"
2017-05-30 09:38:10 -04:00
"time"
qt "github.com/frankban/quicktest"
Introduce a tree map for all content This commit introduces a new data structure to store pages and their resources. This data structure is backed by radix trees. This simplies tree operations, makes all pages a bundle, and paves the way for #6310. It also solves a set of annoying issues (see list below). Not a motivation behind this, but this commit also makes Hugo in general a little bit faster and more memory effective (see benchmarks). Especially for partial rebuilds on content edits, but also when taxonomies is in use. ``` name old time/op new time/op delta SiteNew/Bundle_with_image/Edit-16 1.32ms ± 8% 1.00ms ± 9% -24.42% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 1.28ms ± 0% 0.94ms ± 0% -26.26% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 33.9ms ± 2% 21.8ms ± 1% -35.67% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 40.6ms ± 1% 37.7ms ± 3% -7.20% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 56.7ms ± 0% 51.7ms ± 1% -8.82% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 19.9ms ± 2% 18.3ms ± 3% -7.64% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 37.9ms ± 4% 34.0ms ± 2% -10.28% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 10.7ms ± 0% 10.6ms ± 0% -1.15% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 10.8ms ± 0% 10.7ms ± 0% -1.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 43.2ms ± 1% 39.6ms ± 1% -8.35% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 47.6ms ± 1% 47.3ms ± 0% ~ (p=0.057 n=4+4) SiteNew/Deep_content_tree-16 73.0ms ± 1% 74.2ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Many_HTML_templates-16 37.9ms ± 0% 38.1ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Page_collections-16 53.6ms ± 1% 54.7ms ± 1% +2.09% (p=0.029 n=4+4) name old alloc/op new alloc/op delta SiteNew/Bundle_with_image/Edit-16 486kB ± 0% 430kB ± 0% -11.47% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 265kB ± 0% 209kB ± 0% -21.06% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 13.6MB ± 0% 8.8MB ± 0% -34.93% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 66.5MB ± 0% 63.9MB ± 0% -3.95% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 28.8MB ± 0% 25.8MB ± 0% -10.55% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 6.16MB ± 0% 5.56MB ± 0% -9.86% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 16.9MB ± 0% 16.0MB ± 0% -5.19% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 2.28MB ± 0% 2.29MB ± 0% +0.35% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 2.07MB ± 0% 2.07MB ± 0% ~ (p=0.114 n=4+4) SiteNew/Tags_and_categories-16 14.3MB ± 0% 13.2MB ± 0% -7.30% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 69.1MB ± 0% 69.0MB ± 0% ~ (p=0.343 n=4+4) SiteNew/Deep_content_tree-16 31.3MB ± 0% 31.8MB ± 0% +1.49% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 10.8MB ± 0% 10.9MB ± 0% +1.11% (p=0.029 n=4+4) SiteNew/Page_collections-16 21.4MB ± 0% 21.6MB ± 0% +1.15% (p=0.029 n=4+4) name old allocs/op new allocs/op delta SiteNew/Bundle_with_image/Edit-16 4.74k ± 0% 3.86k ± 0% -18.57% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 4.73k ± 0% 3.85k ± 0% -18.58% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 301k ± 0% 198k ± 0% -34.14% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 389k ± 0% 373k ± 0% -4.07% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 338k ± 0% 262k ± 0% -22.63% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 102k ± 0% 88k ± 0% -13.81% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 176k ± 0% 152k ± 0% -13.32% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 273k ± 0% 245k ± 0% -10.36% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 396k ± 0% 398k ± 0% +0.39% (p=0.029 n=4+4) SiteNew/Deep_content_tree-16 317k ± 0% 325k ± 0% +2.53% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 146k ± 0% 147k ± 0% +0.98% (p=0.029 n=4+4) SiteNew/Page_collections-16 210k ± 0% 215k ± 0% +2.44% (p=0.029 n=4+4) ``` Fixes #6312 Fixes #6087 Fixes #6738 Fixes #6412 Fixes #6743 Fixes #6875 Fixes #6034 Fixes #6902 Fixes #6173 Fixes #6590
2019-09-10 05:26:34 -04:00
"github.com/gohugoio/hugo/htesting"
"github.com/gohugoio/hugo/resources/page"
2017-02-22 03:39:57 -05:00
"github.com/fortytw2/leaktest"
"github.com/fsnotify/fsnotify"
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs"
"github.com/spf13/afero"
)
func TestMultiSitesMainLangInRoot(t *testing.T) {
t.Parallel()
2018-03-16 13:27:44 -04:00
for _, b := range []bool{false} {
doTestMultiSitesMainLangInRoot(t, b)
}
}
func doTestMultiSitesMainLangInRoot(t *testing.T, defaultInSubDir bool) {
c := qt.New(t)
siteConfig := map[string]any{
2018-03-16 13:27:44 -04:00
"DefaultContentLanguage": "fr",
"DefaultContentLanguageInSubdir": defaultInSubDir,
}
2018-03-16 13:27:44 -04:00
b := newMultiSiteTestBuilder(t, "toml", multiSiteTOMLConfigTemplate, siteConfig)
2018-03-16 13:27:44 -04:00
pathMod := func(s string) string {
return s
}
2018-03-16 13:27:44 -04:00
if !defaultInSubDir {
pathMod = func(s string) string {
return strings.Replace(s, "/fr/", "/", -1)
}
}
2018-03-16 13:27:44 -04:00
b.CreateSites()
b.Build(BuildCfg{})
2018-03-16 13:27:44 -04:00
sites := b.H.Sites
c.Assert(len(sites), qt.Equals, 4)
2018-03-16 13:27:44 -04:00
enSite := sites[0]
frSite := sites[1]
c.Assert(enSite.Info.LanguagePrefix, qt.Equals, "/en")
if defaultInSubDir {
c.Assert(frSite.Info.LanguagePrefix, qt.Equals, "/fr")
} else {
c.Assert(frSite.Info.LanguagePrefix, qt.Equals, "")
}
c.Assert(enSite.PathSpec.RelURL("foo", true), qt.Equals, "/blog/en/foo")
doc1en := enSite.RegularPages()[0]
doc1fr := frSite.RegularPages()[0]
enPerm := doc1en.Permalink()
enRelPerm := doc1en.RelPermalink()
c.Assert(enPerm, qt.Equals, "http://example.com/blog/en/sect/doc1-slug/")
c.Assert(enRelPerm, qt.Equals, "/blog/en/sect/doc1-slug/")
frPerm := doc1fr.Permalink()
frRelPerm := doc1fr.RelPermalink()
2018-03-16 13:27:44 -04:00
b.AssertFileContent(pathMod("public/fr/sect/doc1/index.html"), "Single", "Bonjour")
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Hello")
if defaultInSubDir {
c.Assert(frPerm, qt.Equals, "http://example.com/blog/fr/sect/doc1/")
c.Assert(frRelPerm, qt.Equals, "/blog/fr/sect/doc1/")
2018-03-16 13:27:44 -04:00
// should have a redirect on top level.
b.AssertFileContent("public/index.html", `<meta http-equiv="refresh" content="0; url=http://example.com/blog/fr">`)
} else {
2018-03-16 13:27:44 -04:00
// Main language in root
c.Assert(frPerm, qt.Equals, "http://example.com/blog/sect/doc1/")
c.Assert(frRelPerm, qt.Equals, "/blog/sect/doc1/")
2018-03-16 13:27:44 -04:00
// should have redirect back to root
b.AssertFileContent("public/fr/index.html", `<meta http-equiv="refresh" content="0; url=http://example.com/blog">`)
}
2018-03-16 13:27:44 -04:00
b.AssertFileContent(pathMod("public/fr/index.html"), "Home", "Bonjour")
b.AssertFileContent("public/en/index.html", "Home", "Hello")
// Check list pages
2018-03-16 13:27:44 -04:00
b.AssertFileContent(pathMod("public/fr/sect/index.html"), "List", "Bonjour")
b.AssertFileContent("public/en/sect/index.html", "List", "Hello")
b.AssertFileContent(pathMod("public/fr/plaques/FRtag1/index.html"), "Taxonomy List", "Bonjour")
b.AssertFileContent("public/en/tags/tag1/index.html", "Taxonomy List", "Hello")
// Check sitemaps
// Sitemaps behaves different: In a multilanguage setup there will always be a index file and
// one sitemap in each lang folder.
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/sitemap.xml",
"<loc>http://example.com/blog/en/sitemap.xml</loc>",
"<loc>http://example.com/blog/fr/sitemap.xml</loc>")
if defaultInSubDir {
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/fr/sitemap.xml", "<loc>http://example.com/blog/fr/</loc>")
} else {
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/fr/sitemap.xml", "<loc>http://example.com/blog/</loc>")
}
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/sitemap.xml", "<loc>http://example.com/blog/en/</loc>")
// Check rss
2018-03-16 13:27:44 -04:00
b.AssertFileContent(pathMod("public/fr/index.xml"), pathMod(`<atom:link href="http://example.com/blog/fr/index.xml"`),
`rel="self" type="application/rss+xml"`)
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/index.xml", `<atom:link href="http://example.com/blog/en/index.xml"`)
b.AssertFileContent(
pathMod("public/fr/sect/index.xml"),
pathMod(`<atom:link href="http://example.com/blog/fr/sect/index.xml"`))
b.AssertFileContent("public/en/sect/index.xml", `<atom:link href="http://example.com/blog/en/sect/index.xml"`)
b.AssertFileContent(
pathMod("public/fr/plaques/FRtag1/index.xml"),
pathMod(`<atom:link href="http://example.com/blog/fr/plaques/FRtag1/index.xml"`))
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/tags/tag1/index.xml", `<atom:link href="http://example.com/blog/en/tags/tag1/index.xml"`)
// Check paginators
2018-03-16 13:27:44 -04:00
b.AssertFileContent(pathMod("public/fr/page/1/index.html"), pathMod(`refresh" content="0; url=http://example.com/blog/fr/"`))
b.AssertFileContent("public/en/page/1/index.html", `refresh" content="0; url=http://example.com/blog/en/"`)
b.AssertFileContent(pathMod("public/fr/page/2/index.html"), "Home Page 2", "Bonjour", pathMod("http://example.com/blog/fr/"))
b.AssertFileContent("public/en/page/2/index.html", "Home Page 2", "Hello", "http://example.com/blog/en/")
b.AssertFileContent(pathMod("public/fr/sect/page/1/index.html"), pathMod(`refresh" content="0; url=http://example.com/blog/fr/sect/"`))
b.AssertFileContent("public/en/sect/page/1/index.html", `refresh" content="0; url=http://example.com/blog/en/sect/"`)
b.AssertFileContent(pathMod("public/fr/sect/page/2/index.html"), "List Page 2", "Bonjour", pathMod("http://example.com/blog/fr/sect/"))
b.AssertFileContent("public/en/sect/page/2/index.html", "List Page 2", "Hello", "http://example.com/blog/en/sect/")
b.AssertFileContent(
pathMod("public/fr/plaques/FRtag1/page/1/index.html"),
pathMod(`refresh" content="0; url=http://example.com/blog/fr/plaques/FRtag1/"`))
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/tags/tag1/page/1/index.html", `refresh" content="0; url=http://example.com/blog/en/tags/tag1/"`)
b.AssertFileContent(
pathMod("public/fr/plaques/FRtag1/page/2/index.html"), "List Page 2", "Bonjour",
pathMod("http://example.com/blog/fr/plaques/FRtag1/"))
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/tags/tag1/page/2/index.html", "List Page 2", "Hello", "http://example.com/blog/en/tags/tag1/")
// nn (Nynorsk) and nb (Bokmål) have custom pagePath: side ("page" in Norwegian)
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/nn/side/1/index.html", `refresh" content="0; url=http://example.com/blog/nn/"`)
b.AssertFileContent("public/nb/side/1/index.html", `refresh" content="0; url=http://example.com/blog/nb/"`)
}
func TestMultiSitesWithTwoLanguages(t *testing.T) {
t.Parallel()
c := qt.New(t)
2018-03-17 14:24:02 -04:00
b := newTestSitesBuilder(t).WithConfigFile("toml", `
defaultContentLanguage = "nn"
[languages]
[languages.nn]
languageName = "Nynorsk"
weight = 1
title = "Tittel på Nynorsk"
[languages.nn.params]
p1 = "p1nn"
[languages.en]
title = "Title in English"
languageName = "English"
weight = 2
[languages.en.params]
p1 = "p1en"
2018-03-16 13:27:44 -04:00
`)
2018-03-16 13:27:44 -04:00
b.CreateSites()
b.Build(BuildCfg{SkipRender: true})
sites := b.H.Sites
c.Assert(len(sites), qt.Equals, 2)
2018-03-16 13:27:44 -04:00
nnSite := sites[0]
nnHome := nnSite.getPage(page.KindHome)
c.Assert(len(nnHome.AllTranslations()), qt.Equals, 2)
c.Assert(len(nnHome.Translations()), qt.Equals, 1)
c.Assert(nnHome.IsTranslated(), qt.Equals, true)
enHome := sites[1].getPage(page.KindHome)
p1, err := enHome.Param("p1")
c.Assert(err, qt.IsNil)
c.Assert(p1, qt.Equals, "p1en")
p1, err = nnHome.Param("p1")
c.Assert(err, qt.IsNil)
c.Assert(p1, qt.Equals, "p1nn")
}
func TestMultiSitesBuild(t *testing.T) {
for _, config := range []struct {
content string
suffix string
}{
2016-09-21 08:09:41 -04:00
{multiSiteTOMLConfigTemplate, "toml"},
{multiSiteYAMLConfigTemplate, "yml"},
{multiSiteJSONConfigTemplate, "json"},
} {
t.Run(config.suffix, func(t *testing.T) {
t.Parallel()
doTestMultiSitesBuild(t, config.content, config.suffix)
})
}
}
2016-09-21 08:09:41 -04:00
func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
c := qt.New(t)
2018-03-16 13:27:44 -04:00
b := newMultiSiteTestBuilder(t, configSuffix, configTemplate, nil)
b.CreateSites()
2018-03-16 13:27:44 -04:00
sites := b.H.Sites
c.Assert(len(sites), qt.Equals, 4)
2018-03-16 13:27:44 -04:00
b.Build(BuildCfg{})
// Check site config
2018-03-16 13:27:44 -04:00
for _, s := range sites {
c.Assert(s.Info.defaultContentLanguageInSubdir, qt.Equals, true)
c.Assert(s.disabledKinds, qt.Not(qt.IsNil))
}
2018-03-16 13:27:44 -04:00
gp1 := b.H.GetContentPage(filepath.FromSlash("content/sect/doc1.en.md"))
c.Assert(gp1, qt.Not(qt.IsNil))
c.Assert(gp1.Title(), qt.Equals, "doc1")
2018-03-16 13:27:44 -04:00
gp2 := b.H.GetContentPage(filepath.FromSlash("content/dummysect/notfound.md"))
c.Assert(gp2, qt.IsNil)
2018-03-16 13:27:44 -04:00
enSite := sites[0]
enSiteHome := enSite.getPage(page.KindHome)
c.Assert(enSiteHome.IsTranslated(), qt.Equals, true)
c.Assert(enSite.language.Lang, qt.Equals, "en")
// dumpPages(enSite.RegularPages()...)
c.Assert(len(enSite.RegularPages()), qt.Equals, 5)
c.Assert(len(enSite.AllPages()), qt.Equals, 32)
// Check 404s
b.AssertFileContent("public/en/404.html", "404|en|404 Page not found")
b.AssertFileContent("public/fr/404.html", "404|fr|404 Page not found")
// Check robots.txt
// 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/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/doc2/index.html", "Permalink: http://example.com/blog/en/sect/doc2/")
b.AssertFileContent("public/superbob/index.html", "Permalink: http://example.com/blog/superbob/")
doc2 := enSite.RegularPages()[1]
doc3 := enSite.RegularPages()[2]
c.Assert(doc3, qt.Equals, doc2.Prev())
doc1en := enSite.RegularPages()[0]
doc1fr := doc1en.Translations()[0]
b.AssertFileContent("public/fr/sect/doc1/index.html", "Permalink: http://example.com/blog/fr/sect/doc1/")
c.Assert(doc1fr, qt.Equals, doc1en.Translations()[0])
c.Assert(doc1en, qt.Equals, doc1fr.Translations()[0])
c.Assert(doc1fr.Language().Lang, qt.Equals, "fr")
doc4 := enSite.AllPages()[4]
c.Assert(len(doc4.Translations()), qt.Equals, 0)
// Taxonomies and their URLs
Introduce a tree map for all content This commit introduces a new data structure to store pages and their resources. This data structure is backed by radix trees. This simplies tree operations, makes all pages a bundle, and paves the way for #6310. It also solves a set of annoying issues (see list below). Not a motivation behind this, but this commit also makes Hugo in general a little bit faster and more memory effective (see benchmarks). Especially for partial rebuilds on content edits, but also when taxonomies is in use. ``` name old time/op new time/op delta SiteNew/Bundle_with_image/Edit-16 1.32ms ± 8% 1.00ms ± 9% -24.42% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 1.28ms ± 0% 0.94ms ± 0% -26.26% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 33.9ms ± 2% 21.8ms ± 1% -35.67% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 40.6ms ± 1% 37.7ms ± 3% -7.20% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 56.7ms ± 0% 51.7ms ± 1% -8.82% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 19.9ms ± 2% 18.3ms ± 3% -7.64% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 37.9ms ± 4% 34.0ms ± 2% -10.28% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 10.7ms ± 0% 10.6ms ± 0% -1.15% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 10.8ms ± 0% 10.7ms ± 0% -1.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 43.2ms ± 1% 39.6ms ± 1% -8.35% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 47.6ms ± 1% 47.3ms ± 0% ~ (p=0.057 n=4+4) SiteNew/Deep_content_tree-16 73.0ms ± 1% 74.2ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Many_HTML_templates-16 37.9ms ± 0% 38.1ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Page_collections-16 53.6ms ± 1% 54.7ms ± 1% +2.09% (p=0.029 n=4+4) name old alloc/op new alloc/op delta SiteNew/Bundle_with_image/Edit-16 486kB ± 0% 430kB ± 0% -11.47% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 265kB ± 0% 209kB ± 0% -21.06% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 13.6MB ± 0% 8.8MB ± 0% -34.93% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 66.5MB ± 0% 63.9MB ± 0% -3.95% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 28.8MB ± 0% 25.8MB ± 0% -10.55% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 6.16MB ± 0% 5.56MB ± 0% -9.86% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 16.9MB ± 0% 16.0MB ± 0% -5.19% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 2.28MB ± 0% 2.29MB ± 0% +0.35% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 2.07MB ± 0% 2.07MB ± 0% ~ (p=0.114 n=4+4) SiteNew/Tags_and_categories-16 14.3MB ± 0% 13.2MB ± 0% -7.30% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 69.1MB ± 0% 69.0MB ± 0% ~ (p=0.343 n=4+4) SiteNew/Deep_content_tree-16 31.3MB ± 0% 31.8MB ± 0% +1.49% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 10.8MB ± 0% 10.9MB ± 0% +1.11% (p=0.029 n=4+4) SiteNew/Page_collections-16 21.4MB ± 0% 21.6MB ± 0% +1.15% (p=0.029 n=4+4) name old allocs/op new allocs/op delta SiteNew/Bundle_with_image/Edit-16 4.74k ± 0% 3.86k ± 0% -18.57% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 4.73k ± 0% 3.85k ± 0% -18.58% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 301k ± 0% 198k ± 0% -34.14% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 389k ± 0% 373k ± 0% -4.07% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 338k ± 0% 262k ± 0% -22.63% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 102k ± 0% 88k ± 0% -13.81% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 176k ± 0% 152k ± 0% -13.32% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 273k ± 0% 245k ± 0% -10.36% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 396k ± 0% 398k ± 0% +0.39% (p=0.029 n=4+4) SiteNew/Deep_content_tree-16 317k ± 0% 325k ± 0% +2.53% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 146k ± 0% 147k ± 0% +0.98% (p=0.029 n=4+4) SiteNew/Page_collections-16 210k ± 0% 215k ± 0% +2.44% (p=0.029 n=4+4) ``` Fixes #6312 Fixes #6087 Fixes #6738 Fixes #6412 Fixes #6743 Fixes #6875 Fixes #6034 Fixes #6902 Fixes #6173 Fixes #6590
2019-09-10 05:26:34 -04:00
c.Assert(len(enSite.Taxonomies()), qt.Equals, 1)
tags := enSite.Taxonomies()["tags"]
c.Assert(len(tags), qt.Equals, 2)
c.Assert(doc1en, qt.Equals, tags["tag1"][0].Page)
2018-03-16 13:27:44 -04:00
frSite := sites[1]
c.Assert(frSite.language.Lang, qt.Equals, "fr")
c.Assert(len(frSite.RegularPages()), qt.Equals, 4)
c.Assert(len(frSite.AllPages()), qt.Equals, 32)
for _, frenchPage := range frSite.RegularPages() {
p := frenchPage
c.Assert(p.Language().Lang, qt.Equals, "fr")
}
// See https://github.com/gohugoio/hugo/issues/4285
// Before Hugo 0.33 you had to be explicit with the content path to get the correct Page, which
// isn't ideal in a multilingual setup. You want a way to get the current language version if available.
// Now you can do lookups with translation base name to get that behaviour.
// Let us test all the regular page variants:
getPageDoc1En := enSite.getPage(page.KindPage, filepath.ToSlash(doc1en.File().Path()))
getPageDoc1EnBase := enSite.getPage(page.KindPage, "sect/doc1")
getPageDoc1Fr := frSite.getPage(page.KindPage, filepath.ToSlash(doc1fr.File().Path()))
getPageDoc1FrBase := frSite.getPage(page.KindPage, "sect/doc1")
c.Assert(getPageDoc1En, qt.Equals, doc1en)
c.Assert(getPageDoc1Fr, qt.Equals, doc1fr)
c.Assert(getPageDoc1EnBase, qt.Equals, doc1en)
c.Assert(getPageDoc1FrBase, qt.Equals, doc1fr)
// Check redirect to main language, French
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/index.html", "0; url=http://example.com/blog/fr")
2016-08-11 12:26:45 -04:00
// check home page content (including data files rendering)
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/index.html", "Default Home Page 1", "Hello", "Hugo Rocks!")
b.AssertFileContent("public/fr/index.html", "French Home Page 1", "Bonjour", "Hugo Rocks!")
2016-08-11 12:26:45 -04:00
// check single page content
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/fr/sect/doc1/index.html", "Single", "Shortcode: Bonjour", "LingoFrench")
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Shortcode: Hello", "LingoDefault")
// Check node translations
homeEn := enSite.getPage(page.KindHome)
c.Assert(homeEn, qt.Not(qt.IsNil))
c.Assert(len(homeEn.Translations()), qt.Equals, 3)
c.Assert(homeEn.Translations()[0].Language().Lang, qt.Equals, "fr")
c.Assert(homeEn.Translations()[1].Language().Lang, qt.Equals, "nn")
c.Assert(homeEn.Translations()[1].Title(), qt.Equals, "På nynorsk")
c.Assert(homeEn.Translations()[2].Language().Lang, qt.Equals, "nb")
c.Assert(homeEn.Translations()[2].Title(), qt.Equals, "På bokmål")
c.Assert(homeEn.Translations()[2].Language().LanguageName, qt.Equals, "Bokmål")
sectFr := frSite.getPage(page.KindSection, "sect")
c.Assert(sectFr, qt.Not(qt.IsNil))
c.Assert(sectFr.Language().Lang, qt.Equals, "fr")
c.Assert(len(sectFr.Translations()), qt.Equals, 1)
c.Assert(sectFr.Translations()[0].Language().Lang, qt.Equals, "en")
c.Assert(sectFr.Translations()[0].Title(), qt.Equals, "Sects")
2018-03-16 13:27:44 -04:00
nnSite := sites[2]
c.Assert(nnSite.language.Lang, qt.Equals, "nn")
taxNn := nnSite.getPage(page.KindTaxonomy, "lag")
c.Assert(taxNn, qt.Not(qt.IsNil))
c.Assert(len(taxNn.Translations()), qt.Equals, 1)
c.Assert(taxNn.Translations()[0].Language().Lang, qt.Equals, "nb")
taxTermNn := nnSite.getPage(page.KindTerm, "lag", "sogndal")
c.Assert(taxTermNn, qt.Not(qt.IsNil))
c.Assert(nnSite.getPage(page.KindTerm, "LAG", "SOGNDAL"), qt.Equals, taxTermNn)
c.Assert(len(taxTermNn.Translations()), qt.Equals, 1)
c.Assert(taxTermNn.Translations()[0].Language().Lang, qt.Equals, "nb")
// Check sitemap(s)
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/sitemap.xml",
"<loc>http://example.com/blog/en/sitemap.xml</loc>",
"<loc>http://example.com/blog/fr/sitemap.xml</loc>")
b.AssertFileContent("public/en/sitemap.xml", "http://example.com/blog/en/sect/doc2/")
b.AssertFileContent("public/fr/sitemap.xml", "http://example.com/blog/fr/sect/doc1/")
// Check taxonomies
Introduce a tree map for all content This commit introduces a new data structure to store pages and their resources. This data structure is backed by radix trees. This simplies tree operations, makes all pages a bundle, and paves the way for #6310. It also solves a set of annoying issues (see list below). Not a motivation behind this, but this commit also makes Hugo in general a little bit faster and more memory effective (see benchmarks). Especially for partial rebuilds on content edits, but also when taxonomies is in use. ``` name old time/op new time/op delta SiteNew/Bundle_with_image/Edit-16 1.32ms ± 8% 1.00ms ± 9% -24.42% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 1.28ms ± 0% 0.94ms ± 0% -26.26% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 33.9ms ± 2% 21.8ms ± 1% -35.67% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 40.6ms ± 1% 37.7ms ± 3% -7.20% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 56.7ms ± 0% 51.7ms ± 1% -8.82% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 19.9ms ± 2% 18.3ms ± 3% -7.64% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 37.9ms ± 4% 34.0ms ± 2% -10.28% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 10.7ms ± 0% 10.6ms ± 0% -1.15% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 10.8ms ± 0% 10.7ms ± 0% -1.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 43.2ms ± 1% 39.6ms ± 1% -8.35% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 47.6ms ± 1% 47.3ms ± 0% ~ (p=0.057 n=4+4) SiteNew/Deep_content_tree-16 73.0ms ± 1% 74.2ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Many_HTML_templates-16 37.9ms ± 0% 38.1ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Page_collections-16 53.6ms ± 1% 54.7ms ± 1% +2.09% (p=0.029 n=4+4) name old alloc/op new alloc/op delta SiteNew/Bundle_with_image/Edit-16 486kB ± 0% 430kB ± 0% -11.47% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 265kB ± 0% 209kB ± 0% -21.06% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 13.6MB ± 0% 8.8MB ± 0% -34.93% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 66.5MB ± 0% 63.9MB ± 0% -3.95% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 28.8MB ± 0% 25.8MB ± 0% -10.55% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 6.16MB ± 0% 5.56MB ± 0% -9.86% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 16.9MB ± 0% 16.0MB ± 0% -5.19% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 2.28MB ± 0% 2.29MB ± 0% +0.35% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 2.07MB ± 0% 2.07MB ± 0% ~ (p=0.114 n=4+4) SiteNew/Tags_and_categories-16 14.3MB ± 0% 13.2MB ± 0% -7.30% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 69.1MB ± 0% 69.0MB ± 0% ~ (p=0.343 n=4+4) SiteNew/Deep_content_tree-16 31.3MB ± 0% 31.8MB ± 0% +1.49% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 10.8MB ± 0% 10.9MB ± 0% +1.11% (p=0.029 n=4+4) SiteNew/Page_collections-16 21.4MB ± 0% 21.6MB ± 0% +1.15% (p=0.029 n=4+4) name old allocs/op new allocs/op delta SiteNew/Bundle_with_image/Edit-16 4.74k ± 0% 3.86k ± 0% -18.57% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 4.73k ± 0% 3.85k ± 0% -18.58% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 301k ± 0% 198k ± 0% -34.14% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 389k ± 0% 373k ± 0% -4.07% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 338k ± 0% 262k ± 0% -22.63% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 102k ± 0% 88k ± 0% -13.81% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 176k ± 0% 152k ± 0% -13.32% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 273k ± 0% 245k ± 0% -10.36% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 396k ± 0% 398k ± 0% +0.39% (p=0.029 n=4+4) SiteNew/Deep_content_tree-16 317k ± 0% 325k ± 0% +2.53% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 146k ± 0% 147k ± 0% +0.98% (p=0.029 n=4+4) SiteNew/Page_collections-16 210k ± 0% 215k ± 0% +2.44% (p=0.029 n=4+4) ``` Fixes #6312 Fixes #6087 Fixes #6738 Fixes #6412 Fixes #6743 Fixes #6875 Fixes #6034 Fixes #6902 Fixes #6173 Fixes #6590
2019-09-10 05:26:34 -04:00
enTags := enSite.Taxonomies()["tags"]
frTags := frSite.Taxonomies()["plaques"]
c.Assert(len(enTags), qt.Equals, 2, qt.Commentf("Tags in en: %v", enTags))
c.Assert(len(frTags), qt.Equals, 2, qt.Commentf("Tags in fr: %v", frTags))
c.Assert(enTags["tag1"], qt.Not(qt.IsNil))
c.Assert(frTags["FRtag1"], qt.Not(qt.IsNil))
b.AssertFileContent("public/fr/plaques/FRtag1/index.html", "FRtag1|Bonjour|http://example.com/blog/fr/plaques/FRtag1/")
// en and nn have custom site menus
c.Assert(len(frSite.Menus()), qt.Equals, 0)
c.Assert(len(enSite.Menus()), qt.Equals, 1)
c.Assert(len(nnSite.Menus()), qt.Equals, 1)
c.Assert(enSite.Menus()["main"].ByName()[0].Name, qt.Equals, "Home")
c.Assert(nnSite.Menus()["main"].ByName()[0].Name, qt.Equals, "Heim")
// Issue #3108
prevPage := enSite.RegularPages()[0].Prev()
c.Assert(prevPage, qt.Not(qt.IsNil))
c.Assert(prevPage.Kind(), qt.Equals, page.KindPage)
for {
if prevPage == nil {
break
}
c.Assert(prevPage.Kind(), qt.Equals, page.KindPage)
prevPage = prevPage.Prev()
}
// Check bundles
b.AssertFileContent("public/fr/bundles/b1/index.html", "RelPermalink: /blog/fr/bundles/b1/|")
bundleFr := frSite.getPage(page.KindPage, "bundles/b1/index.md")
c.Assert(bundleFr, qt.Not(qt.IsNil))
c.Assert(len(bundleFr.Resources()), qt.Equals, 1)
logoFr := bundleFr.Resources().GetMatch("logo*")
logoFrGet := bundleFr.Resources().Get("logo.png")
c.Assert(logoFrGet, qt.Equals, logoFr)
c.Assert(logoFr, qt.Not(qt.IsNil))
b.AssertFileContent("public/fr/bundles/b1/index.html", "Resources: image/png: /blog/fr/bundles/b1/logo.png")
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/fr/bundles/b1/logo.png", "PNG Data")
bundleEn := enSite.getPage(page.KindPage, "bundles/b1/index.en.md")
c.Assert(bundleEn, qt.Not(qt.IsNil))
b.AssertFileContent("public/en/bundles/b1/index.html", "RelPermalink: /blog/en/bundles/b1/|")
c.Assert(len(bundleEn.Resources()), qt.Equals, 1)
logoEn := bundleEn.Resources().GetMatch("logo*")
c.Assert(logoEn, qt.Not(qt.IsNil))
b.AssertFileContent("public/en/bundles/b1/index.html", "Resources: image/png: /blog/en/bundles/b1/logo.png")
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/bundles/b1/logo.png", "PNG Data")
}
func TestMultiSitesRebuild(t *testing.T) {
// t.Parallel() not supported, see https://github.com/fortytw2/leaktest/issues/4
2017-06-13 15:22:47 -04:00
// This leaktest seems to be a little bit shaky on Travis.
if !htesting.IsCI() {
2018-03-21 12:21:46 -04:00
defer leaktest.CheckTimeout(t, 10*time.Second)()
2017-06-13 15:22:47 -04:00
}
c := qt.New(t)
2018-03-16 13:27:44 -04:00
b := newMultiSiteTestDefaultBuilder(t).Running().CreateSites().Build(BuildCfg{})
2018-03-16 13:27:44 -04:00
sites := b.H.Sites
fs := b.Fs
b.AssertFileContent("public/en/sect/doc2/index.html", "Single: doc2|Hello|en|", "\n\n<h1 id=\"doc2\">doc2</h1>\n\n<p><em>some content</em>")
2018-03-16 13:27:44 -04:00
enSite := sites[0]
frSite := sites[1]
c.Assert(len(enSite.RegularPages()), qt.Equals, 5)
c.Assert(len(frSite.RegularPages()), qt.Equals, 4)
// Verify translations
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Hello")
b.AssertFileContent("public/fr/sect/doc1/index.html", "Bonjour")
// check single page content
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/fr/sect/doc1/index.html", "Single", "Shortcode: Bonjour")
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Shortcode: Hello")
homeEn := enSite.getPage(page.KindHome)
c.Assert(homeEn, qt.Not(qt.IsNil))
c.Assert(len(homeEn.Translations()), qt.Equals, 3)
contentFs := b.H.Fs.Source
2018-03-21 12:21:46 -04:00
for i, this := range []struct {
preFunc func(t *testing.T)
events []fsnotify.Event
assertFunc func(t *testing.T)
}{
// * Remove doc
// * Add docs existing languages
// (Add doc new language: TODO(bep) we should load config.toml as part of these so we can add languages).
// * Rename file
// * Change doc
// * Change a template
// * Change language file
{
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
func(t *testing.T) {
fs.Source.Remove("content/sect/doc2.en.md")
},
[]fsnotify.Event{{Name: filepath.FromSlash("content/sect/doc2.en.md"), Op: fsnotify.Remove}},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 4, qt.Commentf("1 en removed"))
},
},
{
func(t *testing.T) {
writeNewContentFile(t, contentFs, "new_en_1", "2016-07-31", "content/new1.en.md", -5)
writeNewContentFile(t, contentFs, "new_en_2", "1989-07-30", "content/new2.en.md", -10)
writeNewContentFile(t, contentFs, "new_fr_1", "2016-07-30", "content/new1.fr.md", 10)
},
[]fsnotify.Event{
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
{Name: filepath.FromSlash("content/new1.en.md"), Op: fsnotify.Create},
{Name: filepath.FromSlash("content/new2.en.md"), Op: fsnotify.Create},
{Name: filepath.FromSlash("content/new1.fr.md"), Op: fsnotify.Create},
},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 6)
c.Assert(len(enSite.AllPages()), qt.Equals, 34)
c.Assert(len(frSite.RegularPages()), qt.Equals, 5)
c.Assert(frSite.RegularPages()[3].Title(), qt.Equals, "new_fr_1")
c.Assert(enSite.RegularPages()[0].Title(), qt.Equals, "new_en_2")
c.Assert(enSite.RegularPages()[1].Title(), qt.Equals, "new_en_1")
rendered := readWorkingDir(t, fs, "public/en/new1/index.html")
c.Assert(strings.Contains(rendered, "new_en_1"), qt.Equals, true)
},
},
{
func(t *testing.T) {
p := "content/sect/doc1.en.md"
2018-03-21 12:21:46 -04:00
doc1 := readFileFromFs(t, contentFs, p)
doc1 += "CHANGED"
2018-03-21 12:21:46 -04:00
writeToFs(t, contentFs, p, doc1)
},
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
[]fsnotify.Event{{Name: filepath.FromSlash("content/sect/doc1.en.md"), Op: fsnotify.Write}},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 6)
doc1 := readWorkingDir(t, fs, "public/en/sect/doc1-slug/index.html")
c.Assert(strings.Contains(doc1, "CHANGED"), qt.Equals, true)
},
},
// Rename a file
{
func(t *testing.T) {
if err := contentFs.Rename("content/new1.en.md", "content/new1renamed.en.md"); err != nil {
t.Fatalf("Rename failed: %s", err)
}
},
[]fsnotify.Event{
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
{Name: filepath.FromSlash("content/new1renamed.en.md"), Op: fsnotify.Rename},
{Name: filepath.FromSlash("content/new1.en.md"), Op: fsnotify.Rename},
},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 6, qt.Commentf("Rename"))
c.Assert(enSite.RegularPages()[1].Title(), qt.Equals, "new_en_1")
rendered := readWorkingDir(t, fs, "public/en/new1renamed/index.html")
c.Assert(rendered, qt.Contains, "new_en_1")
},
},
{
// Change a template
func(t *testing.T) {
template := "layouts/_default/single.html"
templateContent := readSource(t, fs, template)
templateContent += "{{ print \"Template Changed\"}}"
writeSource(t, fs, template, templateContent)
},
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
[]fsnotify.Event{{Name: filepath.FromSlash("layouts/_default/single.html"), Op: fsnotify.Write}},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 6)
c.Assert(len(enSite.AllPages()), qt.Equals, 34)
c.Assert(len(frSite.RegularPages()), qt.Equals, 5)
doc1 := readWorkingDir(t, fs, "public/en/sect/doc1-slug/index.html")
c.Assert(strings.Contains(doc1, "Template Changed"), qt.Equals, true)
},
},
{
// Change a language file
func(t *testing.T) {
languageFile := "i18n/fr.yaml"
langContent := readSource(t, fs, languageFile)
langContent = strings.Replace(langContent, "Bonjour", "Salut", 1)
writeSource(t, fs, languageFile, langContent)
},
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
[]fsnotify.Event{{Name: filepath.FromSlash("i18n/fr.yaml"), Op: fsnotify.Write}},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 6)
c.Assert(len(enSite.AllPages()), qt.Equals, 34)
c.Assert(len(frSite.RegularPages()), qt.Equals, 5)
docEn := readWorkingDir(t, fs, "public/en/sect/doc1-slug/index.html")
c.Assert(strings.Contains(docEn, "Hello"), qt.Equals, true)
docFr := readWorkingDir(t, fs, "public/fr/sect/doc1/index.html")
c.Assert(strings.Contains(docFr, "Salut"), qt.Equals, true)
homeEn := enSite.getPage(page.KindHome)
c.Assert(homeEn, qt.Not(qt.IsNil))
c.Assert(len(homeEn.Translations()), qt.Equals, 3)
c.Assert(homeEn.Translations()[0].Language().Lang, qt.Equals, "fr")
},
},
// Change a shortcode
{
func(t *testing.T) {
writeSource(t, fs, "layouts/shortcodes/shortcode.html", "Modified Shortcode: {{ i18n \"hello\" }}")
},
[]fsnotify.Event{
:sparkles: Implement Page bundling and image handling This commit is not the smallest in Hugo's history. Some hightlights include: * Page bundles (for complete articles, keeping images and content together etc.). * Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`. * Processed images are cached inside `resources/_gen/images` (default) in your project. * Symbolic links (both files and dirs) are now allowed anywhere inside /content * A new table based build summary * The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below). A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory: ```bash ▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render" benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12% BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35% BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64% ``` Fixes #3651 Closes #3158 Fixes #1014 Closes #2021 Fixes #1240 Updates #3757
2017-07-24 03:00:23 -04:00
{Name: filepath.FromSlash("layouts/shortcodes/shortcode.html"), Op: fsnotify.Write},
},
func(t *testing.T) {
c.Assert(len(enSite.RegularPages()), qt.Equals, 6)
c.Assert(len(enSite.AllPages()), qt.Equals, 34)
c.Assert(len(frSite.RegularPages()), qt.Equals, 5)
2018-03-16 13:27:44 -04:00
b.AssertFileContent("public/fr/sect/doc1/index.html", "Single", "Modified Shortcode: Salut")
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Modified Shortcode: Hello")
},
},
} {
if this.preFunc != nil {
this.preFunc(t)
}
2018-03-16 13:27:44 -04:00
err := b.H.Build(BuildCfg{}, this.events...)
if err != nil {
t.Fatalf("[%d] Failed to rebuild sites: %s", i, err)
}
this.assertFunc(t)
}
}
// https://github.com/gohugoio/hugo/issues/4706
func TestContentStressTest(t *testing.T) {
b := newTestSitesBuilder(t)
numPages := 500
contentTempl := `
---
%s
title: %q
weight: %d
multioutput: %t
---
# Header
CONTENT
The End.
`
contentTempl = strings.Replace(contentTempl, "CONTENT", strings.Repeat(`
## Another header
Some text. Some more text.
`, 100), -1)
var content []string
defaultOutputs := `outputs: ["html", "json", "rss" ]`
for i := 1; i <= numPages; i++ {
outputs := defaultOutputs
multioutput := true
if i%3 == 0 {
outputs = `outputs: ["json"]`
multioutput = false
}
section := "s1"
if i%10 == 0 {
section = "s2"
}
content = append(content, []string{fmt.Sprintf("%s/page%d.md", section, i), fmt.Sprintf(contentTempl, outputs, fmt.Sprintf("Title %d", i), i, multioutput)}...)
}
content = append(content, []string{"_index.md", fmt.Sprintf(contentTempl, defaultOutputs, fmt.Sprintf("Home %d", 0), 0, true)}...)
content = append(content, []string{"s1/_index.md", fmt.Sprintf(contentTempl, defaultOutputs, fmt.Sprintf("S %d", 1), 1, true)}...)
content = append(content, []string{"s2/_index.md", fmt.Sprintf(contentTempl, defaultOutputs, fmt.Sprintf("S %d", 2), 2, true)}...)
b.WithSimpleConfigFile()
b.WithTemplates("layouts/_default/single.html", `Single: {{ .Content }}|RelPermalink: {{ .RelPermalink }}|Permalink: {{ .Permalink }}`)
b.WithTemplates("layouts/_default/myview.html", `View: {{ len .Content }}`)
b.WithTemplates("layouts/_default/single.json", `Single JSON: {{ .Content }}|RelPermalink: {{ .RelPermalink }}|Permalink: {{ .Permalink }}`)
b.WithTemplates("layouts/_default/list.html", `
Page: {{ .Paginator.PageNumber }}
P: {{ with .File }}{{ path.Join .Path }}{{ end }}
List: {{ len .Paginator.Pages }}|List Content: {{ len .Content }}
{{ $shuffled := where .Site.RegularPages "Params.multioutput" true | shuffle }}
{{ $first5 := $shuffled | first 5 }}
L1: {{ len .Site.RegularPages }} L2: {{ len $first5 }}
{{ range $i, $e := $first5 }}
Render {{ $i }}: {{ .Render "myview" }}
{{ end }}
END
`)
b.WithContent(content...)
b.CreateSites().Build(BuildCfg{})
contentMatchers := []string{"<h2 id=\"another-header\">Another header</h2>", "<h2 id=\"another-header-99\">Another header</h2>", "<p>The End.</p>"}
for i := 1; i <= numPages; i++ {
if i%3 != 0 {
section := "s1"
if i%10 == 0 {
section = "s2"
}
checkContent(b, fmt.Sprintf("public/%s/page%d/index.html", section, i), contentMatchers...)
}
}
for i := 1; i <= numPages; i++ {
section := "s1"
if i%10 == 0 {
section = "s2"
}
checkContent(b, fmt.Sprintf("public/%s/page%d/index.json", section, i), contentMatchers...)
}
checkContent(b, "public/s1/index.html", "P: s1/_index.md\nList: 10|List Content: 8132\n\n\nL1: 500 L2: 5\n\nRender 0: View: 8132\n\nRender 1: View: 8132\n\nRender 2: View: 8132\n\nRender 3: View: 8132\n\nRender 4: View: 8132\n\nEND\n")
checkContent(b, "public/s2/index.html", "P: s2/_index.md\nList: 10|List Content: 8132", "Render 4: View: 8132\n\nEND")
checkContent(b, "public/index.html", "P: _index.md\nList: 10|List Content: 8132", "4: View: 8132\n\nEND")
// Check paginated pages
for i := 2; i <= 9; i++ {
checkContent(b, fmt.Sprintf("public/page/%d/index.html", i), fmt.Sprintf("Page: %d", i), "Content: 8132\n\n\nL1: 500 L2: 5\n\nRender 0: View: 8132", "Render 4: View: 8132\n\nEND")
}
}
func checkContent(s *sitesBuilder, filename string, matches ...string) {
s.T.Helper()
content := readWorkingDir(s.T, s.Fs, filename)
for _, match := range matches {
if !strings.Contains(content, match) {
Introduce a tree map for all content This commit introduces a new data structure to store pages and their resources. This data structure is backed by radix trees. This simplies tree operations, makes all pages a bundle, and paves the way for #6310. It also solves a set of annoying issues (see list below). Not a motivation behind this, but this commit also makes Hugo in general a little bit faster and more memory effective (see benchmarks). Especially for partial rebuilds on content edits, but also when taxonomies is in use. ``` name old time/op new time/op delta SiteNew/Bundle_with_image/Edit-16 1.32ms ± 8% 1.00ms ± 9% -24.42% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 1.28ms ± 0% 0.94ms ± 0% -26.26% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 33.9ms ± 2% 21.8ms ± 1% -35.67% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 40.6ms ± 1% 37.7ms ± 3% -7.20% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 56.7ms ± 0% 51.7ms ± 1% -8.82% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 19.9ms ± 2% 18.3ms ± 3% -7.64% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 37.9ms ± 4% 34.0ms ± 2% -10.28% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 10.7ms ± 0% 10.6ms ± 0% -1.15% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 10.8ms ± 0% 10.7ms ± 0% -1.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 43.2ms ± 1% 39.6ms ± 1% -8.35% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 47.6ms ± 1% 47.3ms ± 0% ~ (p=0.057 n=4+4) SiteNew/Deep_content_tree-16 73.0ms ± 1% 74.2ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Many_HTML_templates-16 37.9ms ± 0% 38.1ms ± 1% ~ (p=0.114 n=4+4) SiteNew/Page_collections-16 53.6ms ± 1% 54.7ms ± 1% +2.09% (p=0.029 n=4+4) name old alloc/op new alloc/op delta SiteNew/Bundle_with_image/Edit-16 486kB ± 0% 430kB ± 0% -11.47% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 265kB ± 0% 209kB ± 0% -21.06% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 13.6MB ± 0% 8.8MB ± 0% -34.93% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 66.5MB ± 0% 63.9MB ± 0% -3.95% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 28.8MB ± 0% 25.8MB ± 0% -10.55% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 6.16MB ± 0% 5.56MB ± 0% -9.86% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 16.9MB ± 0% 16.0MB ± 0% -5.19% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 2.28MB ± 0% 2.29MB ± 0% +0.35% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 2.07MB ± 0% 2.07MB ± 0% ~ (p=0.114 n=4+4) SiteNew/Tags_and_categories-16 14.3MB ± 0% 13.2MB ± 0% -7.30% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 69.1MB ± 0% 69.0MB ± 0% ~ (p=0.343 n=4+4) SiteNew/Deep_content_tree-16 31.3MB ± 0% 31.8MB ± 0% +1.49% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 10.8MB ± 0% 10.9MB ± 0% +1.11% (p=0.029 n=4+4) SiteNew/Page_collections-16 21.4MB ± 0% 21.6MB ± 0% +1.15% (p=0.029 n=4+4) name old allocs/op new allocs/op delta SiteNew/Bundle_with_image/Edit-16 4.74k ± 0% 3.86k ± 0% -18.57% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file/Edit-16 4.73k ± 0% 3.85k ± 0% -18.58% (p=0.029 n=4+4) SiteNew/Tags_and_categories/Edit-16 301k ± 0% 198k ± 0% -34.14% (p=0.029 n=4+4) SiteNew/Canonify_URLs/Edit-16 389k ± 0% 373k ± 0% -4.07% (p=0.029 n=4+4) SiteNew/Deep_content_tree/Edit-16 338k ± 0% 262k ± 0% -22.63% (p=0.029 n=4+4) SiteNew/Many_HTML_templates/Edit-16 102k ± 0% 88k ± 0% -13.81% (p=0.029 n=4+4) SiteNew/Page_collections/Edit-16 176k ± 0% 152k ± 0% -13.32% (p=0.029 n=4+4) SiteNew/Bundle_with_image-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Bundle_with_JSON_file-16 26.8k ± 0% 26.8k ± 0% +0.05% (p=0.029 n=4+4) SiteNew/Tags_and_categories-16 273k ± 0% 245k ± 0% -10.36% (p=0.029 n=4+4) SiteNew/Canonify_URLs-16 396k ± 0% 398k ± 0% +0.39% (p=0.029 n=4+4) SiteNew/Deep_content_tree-16 317k ± 0% 325k ± 0% +2.53% (p=0.029 n=4+4) SiteNew/Many_HTML_templates-16 146k ± 0% 147k ± 0% +0.98% (p=0.029 n=4+4) SiteNew/Page_collections-16 210k ± 0% 215k ± 0% +2.44% (p=0.029 n=4+4) ``` Fixes #6312 Fixes #6087 Fixes #6738 Fixes #6412 Fixes #6743 Fixes #6875 Fixes #6034 Fixes #6902 Fixes #6173 Fixes #6590
2019-09-10 05:26:34 -04:00
s.Fatalf("No match for\n%q\nin content for %s\n%q\nDiff:\n%s", match, filename, content, htesting.DiffStrings(content, match))
}
}
}
func TestTranslationsFromContentToNonContent(t *testing.T) {
b := newTestSitesBuilder(t)
b.WithConfigFile("toml", `
baseURL = "http://example.com/"
defaultContentLanguage = "en"
[languages]
[languages.en]
weight = 10
contentDir = "content/en"
[languages.nn]
weight = 20
contentDir = "content/nn"
`)
b.WithContent("en/mysection/_index.md", `
---
Title: My Section
---
`)
b.WithContent("en/_index.md", `
---
Title: My Home
---
`)
b.WithContent("en/categories/mycat/_index.md", `
---
Title: My MyCat
---
`)
b.WithContent("en/categories/_index.md", `
---
Title: My categories
---
`)
for _, lang := range []string{"en", "nn"} {
b.WithContent(lang+"/mysection/page.md", `
---
Title: My Page
categories: ["mycat"]
---
`)
}
b.Build(BuildCfg{})
for _, path := range []string{
"/",
"/mysection",
"/categories",
"/categories/mycat",
} {
t.Run(path, func(t *testing.T) {
c := qt.New(t)
s1, _ := b.H.Sites[0].getPageNew(nil, path)
s2, _ := b.H.Sites[1].getPageNew(nil, path)
c.Assert(s1, qt.Not(qt.IsNil))
c.Assert(s2, qt.Not(qt.IsNil))
c.Assert(len(s1.Translations()), qt.Equals, 1)
c.Assert(len(s2.Translations()), qt.Equals, 1)
c.Assert(s1.Translations()[0], qt.Equals, s2)
c.Assert(s2.Translations()[0], qt.Equals, s1)
m1 := s1.Translations().MergeByLanguage(s2.Translations())
m2 := s2.Translations().MergeByLanguage(s1.Translations())
c.Assert(len(m1), qt.Equals, 1)
c.Assert(len(m2), qt.Equals, 1)
})
}
}
var tocShortcode = `
TOC1: {{ .Page.TableOfContents }}
TOC2: {{ .Page.TableOfContents }}
`
func TestSelfReferencedContentInShortcode(t *testing.T) {
t.Parallel()
b := newMultiSiteTestDefaultBuilder(t)
var (
shortcode = `{{- .Page.Content -}}{{- .Page.Summary -}}{{- .Page.Plain -}}{{- .Page.PlainWords -}}{{- .Page.WordCount -}}{{- .Page.ReadingTime -}}`
page = `---
title: sctest
---
Empty:{{< mycontent >}}:
`
)
b.WithTemplatesAdded("layouts/shortcodes/mycontent.html", shortcode)
b.WithContent("post/simple.en.md", page)
b.CreateSites().Build(BuildCfg{})
b.AssertFileContent("public/en/post/simple/index.html", "Empty:[]00:")
}
var tocPageSimple = `---
title: tocTest
publishdate: "2000-01-01"
---
{{< toc >}}
# Heading 1 {#1}
Some text.
## Subheading 1.1 {#1-1}
Some more text.
# Heading 2 {#2}
Even more text.
## Subheading 2.1 {#2-1}
Lorem ipsum...
`
var tocPageVariants1 = `---
title: tocTest
publishdate: "2000-01-01"
---
Variant 1:
{{% wrapper %}}
{{< toc >}}
{{% /wrapper %}}
# Heading 1
Variant 3:
{{% toc %}}
`
var tocPageVariants2 = `---
title: tocTest
publishdate: "2000-01-01"
---
Variant 1:
{{% wrapper %}}
{{< toc >}}
{{% /wrapper %}}
# Heading 1
Variant 2:
{{< wrapper >}}
{{< toc >}}
{{< /wrapper >}}
Variant 3:
{{% toc %}}
`
var tocPageSimpleExpected = `<nav id="TableOfContents">
<ul>
<li><a href="#1">Heading 1</a>
<ul>
<li><a href="#1-1">Subheading 1.1</a></li>
</ul></li>
<li><a href="#2">Heading 2</a>
<ul>
<li><a href="#2-1">Subheading 2.1</a></li>
</ul></li>
</ul>
</nav>`
var tocPageWithShortcodesInHeadings = `---
title: tocTest
publishdate: "2000-01-01"
---
{{< toc >}}
# Heading 1 {#1}
Some text.
## Subheading 1.1 {{< shortcode >}} {#1-1}
Some more text.
# Heading 2 {{% shortcode %}} {#2}
Even more text.
## Subheading 2.1 {#2-1}
Lorem ipsum...
`
var tocPageWithShortcodesInHeadingsExpected = `<nav id="TableOfContents">
<ul>
<li><a href="#1">Heading 1</a>
<ul>
<li><a href="#1-1">Subheading 1.1 Shortcode: Hello</a></li>
</ul></li>
<li><a href="#2">Heading 2 Shortcode: Hello</a>
<ul>
<li><a href="#2-1">Subheading 2.1</a></li>
</ul></li>
</ul>
</nav>`
2016-09-21 08:09:41 -04:00
var multiSiteTOMLConfigTemplate = `
baseURL = "http://example.com/blog"
paginate = 1
disablePathToLower = true
defaultContentLanguage = "{{ .DefaultContentLanguage }}"
defaultContentLanguageInSubdir = {{ .DefaultContentLanguageInSubdir }}
enableRobotsTXT = true
[permalinks]
other = "/somewhere/else/:filename"
[Taxonomies]
tag = "tags"
[Languages]
[Languages.en]
weight = 10
2016-09-12 14:57:52 -04:00
title = "In English"
languageName = "English"
[[Languages.en.menu.main]]
url = "/"
name = "Home"
weight = 0
[Languages.fr]
weight = 20
2016-09-12 14:57:52 -04:00
title = "Le Français"
languageName = "Français"
[Languages.fr.Taxonomies]
plaque = "plaques"
[Languages.nn]
weight = 30
2016-09-12 14:57:52 -04:00
title = "På nynorsk"
languageName = "Nynorsk"
paginatePath = "side"
[Languages.nn.Taxonomies]
lag = "lag"
[[Languages.nn.menu.main]]
url = "/"
name = "Heim"
weight = 1
[Languages.nb]
weight = 40
2016-09-12 14:57:52 -04:00
title = "På bokmål"
languageName = "Bokmål"
paginatePath = "side"
[Languages.nb.Taxonomies]
lag = "lag"
`
var multiSiteYAMLConfigTemplate = `
baseURL: "http://example.com/blog"
disablePathToLower: true
paginate: 1
defaultContentLanguage: "{{ .DefaultContentLanguage }}"
defaultContentLanguageInSubdir: {{ .DefaultContentLanguageInSubdir }}
enableRobotsTXT: true
permalinks:
other: "/somewhere/else/:filename"
Taxonomies:
tag: "tags"
Languages:
en:
weight: 10
2016-09-12 14:57:52 -04:00
title: "In English"
languageName: "English"
menu:
main:
- url: "/"
name: "Home"
weight: 0
fr:
weight: 20
2016-09-12 14:57:52 -04:00
title: "Le Français"
languageName: "Français"
Taxonomies:
plaque: "plaques"
nn:
weight: 30
2016-09-12 14:57:52 -04:00
title: "På nynorsk"
languageName: "Nynorsk"
paginatePath: "side"
Taxonomies:
lag: "lag"
menu:
main:
- url: "/"
name: "Heim"
weight: 1
nb:
weight: 40
2016-09-12 14:57:52 -04:00
title: "På bokmål"
languageName: "Bokmål"
paginatePath: "side"
Taxonomies:
lag: "lag"
`
2018-03-16 13:27:44 -04:00
// TODO(bep) clean move
var multiSiteJSONConfigTemplate = `
{
"baseURL": "http://example.com/blog",
"paginate": 1,
"disablePathToLower": true,
"defaultContentLanguage": "{{ .DefaultContentLanguage }}",
"defaultContentLanguageInSubdir": true,
"enableRobotsTXT": true,
"permalinks": {
"other": "/somewhere/else/:filename"
},
"Taxonomies": {
"tag": "tags"
},
"Languages": {
"en": {
"weight": 10,
2016-09-12 14:57:52 -04:00
"title": "In English",
"languageName": "English",
"menu": {
"main": [
{
"url": "/",
"name": "Home",
"weight": 0
}
]
}
},
"fr": {
"weight": 20,
2016-09-12 14:57:52 -04:00
"title": "Le Français",
"languageName": "Français",
"Taxonomies": {
"plaque": "plaques"
}
},
"nn": {
"weight": 30,
2016-09-12 14:57:52 -04:00
"title": "På nynorsk",
"paginatePath": "side",
2016-09-12 14:57:52 -04:00
"languageName": "Nynorsk",
"Taxonomies": {
"lag": "lag"
},
"menu": {
"main": [
{
"url": "/",
"name": "Heim",
"weight": 1
}
]
}
},
"nb": {
"weight": 40,
2016-09-12 14:57:52 -04:00
"title": "På bokmål",
"paginatePath": "side",
2016-09-12 14:57:52 -04:00
"languageName": "Bokmål",
"Taxonomies": {
"lag": "lag"
}
}
}
}
`
2018-03-16 13:27:44 -04:00
func writeSource(t testing.TB, fs *hugofs.Fs, filename, content string) {
t.Helper()
2018-03-16 13:27:44 -04:00
writeToFs(t, fs.Source, filename, content)
}
2018-03-16 13:27:44 -04:00
func writeToFs(t testing.TB, fs afero.Fs, filename, content string) {
t.Helper()
2018-03-16 13:27:44 -04:00
if err := afero.WriteFile(fs, filepath.FromSlash(filename), []byte(content), 0755); err != nil {
t.Fatalf("Failed to write file: %s", err)
}
}
func readWorkingDir(t testing.TB, fs *hugofs.Fs, filename string) string {
t.Helper()
return readFileFromFs(t, fs.WorkingDirReadOnly, filename)
2018-03-16 13:27:44 -04:00
}
func workingDirExists(fs *hugofs.Fs, filename string) bool {
b, err := helpers.Exists(filename, fs.WorkingDirReadOnly)
2018-03-16 13:27:44 -04:00
if err != nil {
panic(err)
}
2018-03-16 13:27:44 -04:00
return b
}
2018-03-16 13:27:44 -04:00
func readSource(t *testing.T, fs *hugofs.Fs, filename string) string {
return readFileFromFs(t, fs.Source, filename)
}
2018-03-16 13:27:44 -04:00
func readFileFromFs(t testing.TB, fs afero.Fs, filename string) string {
t.Helper()
2018-03-16 13:27:44 -04:00
filename = filepath.Clean(filename)
b, err := afero.ReadFile(fs, filename)
if err != nil {
// Print some debug info
hadSlash := strings.HasPrefix(filename, helpers.FilePathSeparator)
start := 0
if hadSlash {
start = 1
}
end := start + 1
parts := strings.Split(filename, helpers.FilePathSeparator)
if parts[start] == "work" {
end++
}
/*
root := filepath.Join(parts[start:end]...)
if hadSlash {
root = helpers.FilePathSeparator + root
}
helpers.PrintFs(fs, root, os.Stdout)
*/
t.Fatalf("Failed to read file: %s", err)
}
2018-03-16 13:27:44 -04:00
return string(b)
}
2018-03-16 13:27:44 -04:00
const testPageTemplate = `---
title: "%s"
publishdate: "%s"
weight: %d
---
# Doc %s
`
2018-03-16 13:27:44 -04:00
func newTestPage(title, date string, weight int) string {
return fmt.Sprintf(testPageTemplate, title, date, weight, title)
}
2018-03-21 12:21:46 -04:00
func writeNewContentFile(t *testing.T, fs afero.Fs, title, date, filename string, weight int) {
2018-03-16 13:27:44 -04:00
content := newTestPage(title, date, weight)
2018-03-21 12:21:46 -04:00
writeToFs(t, fs, filename, content)
2018-03-16 13:27:44 -04:00
}
2018-03-16 13:27:44 -04:00
type multiSiteTestBuilder struct {
configData any
2018-03-16 13:27:44 -04:00
config string
configFormat string
*sitesBuilder
}
func newMultiSiteTestDefaultBuilder(t testing.TB) *multiSiteTestBuilder {
return newMultiSiteTestBuilder(t, "", "", nil)
}
func (b *multiSiteTestBuilder) WithNewConfig(config string) *multiSiteTestBuilder {
b.WithConfigTemplate(b.configData, b.configFormat, config)
return b
}
func (b *multiSiteTestBuilder) WithNewConfigData(data any) *multiSiteTestBuilder {
2018-03-16 13:27:44 -04:00
b.WithConfigTemplate(data, b.configFormat, b.config)
return b
}
func newMultiSiteTestBuilder(t testing.TB, configFormat, config string, configData any) *multiSiteTestBuilder {
2018-03-16 13:27:44 -04:00
if configData == nil {
configData = map[string]any{
2018-03-16 13:27:44 -04:00
"DefaultContentLanguage": "fr",
"DefaultContentLanguageInSubdir": true,
}
}
2018-03-16 13:27:44 -04:00
if config == "" {
config = multiSiteTOMLConfigTemplate
}
2018-03-16 13:27:44 -04:00
if configFormat == "" {
configFormat = "toml"
}
2018-03-16 13:27:44 -04:00
b := newTestSitesBuilder(t).WithConfigTemplate(configData, configFormat, config)
b.WithContent("root.en.md", `---
title: root
weight: 10000
slug: root
publishdate: "2000-01-01"
---
# root
2018-03-16 13:27:44 -04:00
`,
"sect/doc1.en.md", `---
title: doc1
weight: 1
slug: doc1-slug
tags:
- tag1
publishdate: "2000-01-01"
---
# doc1
*some "content"*
{{< shortcode >}}
{{< lingo >}}
NOTE: slug should be used as URL
2018-03-16 13:27:44 -04:00
`,
"sect/doc1.fr.md", `---
title: doc1
weight: 1
plaques:
- FRtag1
- FRtag2
publishdate: "2000-01-04"
---
# doc1
*quelque "contenu"*
{{< shortcode >}}
{{< lingo >}}
NOTE: should be in the 'en' Page's 'Translations' field.
NOTE: date is after "doc3"
2018-03-16 13:27:44 -04:00
`,
"sect/doc2.en.md", `---
title: doc2
weight: 2
publishdate: "2000-01-02"
---
# doc2
*some content*
NOTE: without slug, "doc2" should be used, without ".en" as URL
2018-03-16 13:27:44 -04:00
`,
"sect/doc3.en.md", `---
title: doc3
weight: 3
publishdate: "2000-01-03"
aliases: [/en/al/alias1,/al/alias2/]
tags:
- tag2
- tag1
url: /superbob/
---
# doc3
*some content*
NOTE: third 'en' doc, should trigger pagination on home page.
2018-03-16 13:27:44 -04:00
`,
"sect/doc4.md", `---
title: doc4
weight: 4
plaques:
- FRtag1
publishdate: "2000-01-05"
---
# doc4
*du contenu francophone*
NOTE: should use the defaultContentLanguage and mark this doc as 'fr'.
NOTE: doesn't have any corresponding translation in 'en'
2018-03-16 13:27:44 -04:00
`,
"other/doc5.fr.md", `---
title: doc5
weight: 5
publishdate: "2000-01-06"
---
# doc5
*autre contenu francophone*
NOTE: should use the "permalinks" configuration with :filename
2018-03-16 13:27:44 -04:00
`,
// Add some for the stats
2018-03-16 13:27:44 -04:00
"stats/expired.fr.md", `---
title: expired
publishdate: "2000-01-06"
expiryDate: "2001-01-06"
---
# Expired
2018-03-16 13:27:44 -04:00
`,
"stats/future.fr.md", `---
title: future
weight: 6
publishdate: "2100-01-06"
---
# Future
2018-03-16 13:27:44 -04:00
`,
"stats/expired.en.md", `---
title: expired
weight: 7
publishdate: "2000-01-06"
expiryDate: "2001-01-06"
---
# Expired
2018-03-16 13:27:44 -04:00
`,
"stats/future.en.md", `---
title: future
weight: 6
publishdate: "2100-01-06"
---
# Future
2018-03-16 13:27:44 -04:00
`,
"stats/draft.en.md", `---
title: expired
publishdate: "2000-01-06"
draft: true
---
# Draft
2018-03-16 13:27:44 -04:00
`,
"stats/tax.nn.md", `---
title: Tax NN
weight: 8
publishdate: "2000-01-06"
weight: 1001
lag:
- Sogndal
---
# Tax NN
2018-03-16 13:27:44 -04:00
`,
"stats/tax.nb.md", `---
title: Tax NB
weight: 8
publishdate: "2000-01-06"
weight: 1002
lag:
- Sogndal
---
# Tax NB
2018-03-16 13:27:44 -04:00
`,
// Bundle
2018-03-16 13:27:44 -04:00
"bundles/b1/index.en.md", `---
title: Bundle EN
publishdate: "2000-01-06"
weight: 2001
---
# Bundle Content EN
2018-03-16 13:27:44 -04:00
`,
"bundles/b1/index.md", `---
title: Bundle Default
publishdate: "2000-01-06"
weight: 2002
---
# Bundle Content Default
2018-03-16 13:27:44 -04:00
`,
"bundles/b1/logo.png", `
PNG Data
2018-03-16 13:27:44 -04:00
`)
i18nContent := func(id, value string) string {
return fmt.Sprintf(`
[%s]
other = %q
`, id, value)
}
b.WithSourceFile("i18n/en.toml", i18nContent("hello", "Hello"))
b.WithSourceFile("i18n/fr.toml", i18nContent("hello", "Bonjour"))
b.WithSourceFile("i18n/nb.toml", i18nContent("hello", "Hallo"))
b.WithSourceFile("i18n/nn.toml", i18nContent("hello", "Hallo"))
2018-03-16 13:27:44 -04:00
return &multiSiteTestBuilder{sitesBuilder: b, configFormat: configFormat, config: config, configData: configData}
2016-09-21 08:09:41 -04:00
}
func TestRebuildOnAssetChange(t *testing.T) {
b := newTestSitesBuilder(t).Running()
b.WithTemplatesAdded("index.html", `
{{ (resources.Get "data.json").Content }}
`)
b.WithSourceFile("assets/data.json", "orig data")
b.Build(BuildCfg{})
b.AssertFileContent("public/index.html", `orig data`)
b.EditFiles("assets/data.json", "changed data")
b.Build(BuildCfg{})
b.AssertFileContent("public/index.html", `changed data`)
}